aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2011-10-27 18:05:32 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-10-31 05:22:41 -0400
commit8e35a1398c5db981cd1a2d7635de9c15dd648527 (patch)
tree9a7de3cae5c5a7194a1a447dc871062f351b3363 /drivers/scsi
parent5412e25c55fc0b08041a451d8bee6f2b291099c2 (diff)
[SCSI] isci: Fix hard reset timeout conditions.
A hard reset can timeout before or after the last phy in the port goes away. If after, then notify the OS that the last phy has failed. The recovery for the failed hard reset has been removed. This recovery code was unecessary in that the link would recover from the failure normally by a new link reset sequence or hotplug of the remote device. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/isci/port.c101
-rw-r--r--drivers/scsi/isci/port.h1
2 files changed, 60 insertions, 42 deletions
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 8e59c8865dcd..bfeb87905aaf 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -350,6 +350,34 @@ static void isci_port_stop_complete(struct isci_host *ihost,
350 dev_dbg(&ihost->pdev->dev, "Port stop complete\n"); 350 dev_dbg(&ihost->pdev->dev, "Port stop complete\n");
351} 351}
352 352
353
354static bool is_port_ready_state(enum sci_port_states state)
355{
356 switch (state) {
357 case SCI_PORT_READY:
358 case SCI_PORT_SUB_WAITING:
359 case SCI_PORT_SUB_OPERATIONAL:
360 case SCI_PORT_SUB_CONFIGURING:
361 return true;
362 default:
363 return false;
364 }
365}
366
367/* flag dummy rnc hanling when exiting a ready state */
368static void port_state_machine_change(struct isci_port *iport,
369 enum sci_port_states state)
370{
371 struct sci_base_state_machine *sm = &iport->sm;
372 enum sci_port_states old_state = sm->current_state_id;
373
374 if (is_port_ready_state(old_state) && !is_port_ready_state(state))
375 iport->ready_exit = true;
376
377 sci_change_state(sm, state);
378 iport->ready_exit = false;
379}
380
353/** 381/**
354 * isci_port_hard_reset_complete() - This function is called by the sci core 382 * isci_port_hard_reset_complete() - This function is called by the sci core
355 * when the hard reset complete notification has been received. 383 * when the hard reset complete notification has been received.
@@ -368,6 +396,26 @@ static void isci_port_hard_reset_complete(struct isci_port *isci_port,
368 /* Save the status of the hard reset from the port. */ 396 /* Save the status of the hard reset from the port. */
369 isci_port->hard_reset_status = completion_status; 397 isci_port->hard_reset_status = completion_status;
370 398
399 if (completion_status != SCI_SUCCESS) {
400
401 /* The reset failed. The port state is now SCI_PORT_FAILED. */
402 if (isci_port->active_phy_mask == 0) {
403
404 /* Generate the link down now to the host, since it
405 * was intercepted by the hard reset state machine when
406 * it really happened.
407 */
408 isci_port_link_down(isci_port->isci_host,
409 &isci_port->isci_host->phys[
410 isci_port->last_active_phy],
411 isci_port);
412 }
413 /* Advance the port state so that link state changes will be
414 * noticed.
415 */
416 port_state_machine_change(isci_port, SCI_PORT_SUB_WAITING);
417
418 }
371 complete_all(&isci_port->hard_reset_complete); 419 complete_all(&isci_port->hard_reset_complete);
372} 420}
373 421
@@ -657,6 +705,8 @@ void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy,
657 struct isci_host *ihost = iport->owning_controller; 705 struct isci_host *ihost = iport->owning_controller;
658 706
659 iport->active_phy_mask &= ~(1 << iphy->phy_index); 707 iport->active_phy_mask &= ~(1 << iphy->phy_index);
708 if (!iport->active_phy_mask)
709 iport->last_active_phy = iphy->phy_index;
660 710
661 iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; 711 iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
662 712
@@ -683,33 +733,6 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i
683 } 733 }
684} 734}
685 735
686static bool is_port_ready_state(enum sci_port_states state)
687{
688 switch (state) {
689 case SCI_PORT_READY:
690 case SCI_PORT_SUB_WAITING:
691 case SCI_PORT_SUB_OPERATIONAL:
692 case SCI_PORT_SUB_CONFIGURING:
693 return true;
694 default:
695 return false;
696 }
697}
698
699/* flag dummy rnc hanling when exiting a ready state */
700static void port_state_machine_change(struct isci_port *iport,
701 enum sci_port_states state)
702{
703 struct sci_base_state_machine *sm = &iport->sm;
704 enum sci_port_states old_state = sm->current_state_id;
705
706 if (is_port_ready_state(old_state) && !is_port_ready_state(state))
707 iport->ready_exit = true;
708
709 sci_change_state(sm, state);
710 iport->ready_exit = false;
711}
712
713/** 736/**
714 * sci_port_general_link_up_handler - phy can be assigned to port? 737 * sci_port_general_link_up_handler - phy can be assigned to port?
715 * @sci_port: sci_port object for which has a phy that has gone link up. 738 * @sci_port: sci_port object for which has a phy that has gone link up.
@@ -1622,7 +1645,8 @@ void sci_port_construct(struct isci_port *iport, u8 index,
1622 iport->logical_port_index = SCIC_SDS_DUMMY_PORT; 1645 iport->logical_port_index = SCIC_SDS_DUMMY_PORT;
1623 iport->physical_port_index = index; 1646 iport->physical_port_index = index;
1624 iport->active_phy_mask = 0; 1647 iport->active_phy_mask = 0;
1625 iport->ready_exit = false; 1648 iport->last_active_phy = 0;
1649 iport->ready_exit = false;
1626 1650
1627 iport->owning_controller = ihost; 1651 iport->owning_controller = ihost;
1628 1652
@@ -1676,7 +1700,7 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
1676{ 1700{
1677 unsigned long flags; 1701 unsigned long flags;
1678 enum sci_status status; 1702 enum sci_status status;
1679 int idx, ret = TMF_RESP_FUNC_COMPLETE; 1703 int ret = TMF_RESP_FUNC_COMPLETE;
1680 1704
1681 dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n", 1705 dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n",
1682 __func__, iport); 1706 __func__, iport);
@@ -1697,8 +1721,13 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
1697 "%s: iport = %p; hard reset completion\n", 1721 "%s: iport = %p; hard reset completion\n",
1698 __func__, iport); 1722 __func__, iport);
1699 1723
1700 if (iport->hard_reset_status != SCI_SUCCESS) 1724 if (iport->hard_reset_status != SCI_SUCCESS) {
1701 ret = TMF_RESP_FUNC_FAILED; 1725 ret = TMF_RESP_FUNC_FAILED;
1726
1727 dev_err(&ihost->pdev->dev,
1728 "%s: iport = %p; hard reset failed (0x%x)\n",
1729 __func__, iport, iport->hard_reset_status);
1730 }
1702 } else { 1731 } else {
1703 ret = TMF_RESP_FUNC_FAILED; 1732 ret = TMF_RESP_FUNC_FAILED;
1704 1733
@@ -1718,18 +1747,6 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
1718 "%s: iport = %p; hard reset failed " 1747 "%s: iport = %p; hard reset failed "
1719 "(0x%x) - driving explicit link fail for all phys\n", 1748 "(0x%x) - driving explicit link fail for all phys\n",
1720 __func__, iport, iport->hard_reset_status); 1749 __func__, iport, iport->hard_reset_status);
1721
1722 /* Down all phys in the port. */
1723 spin_lock_irqsave(&ihost->scic_lock, flags);
1724 for (idx = 0; idx < SCI_MAX_PHYS; ++idx) {
1725 struct isci_phy *iphy = iport->phy_table[idx];
1726
1727 if (!iphy)
1728 continue;
1729 sci_phy_stop(iphy);
1730 sci_phy_start(iphy);
1731 }
1732 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1733 } 1750 }
1734 return ret; 1751 return ret;
1735} 1752}
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
index b50ecd4e8f9c..e84d22a309e3 100644
--- a/drivers/scsi/isci/port.h
+++ b/drivers/scsi/isci/port.h
@@ -109,6 +109,7 @@ struct isci_port {
109 u8 logical_port_index; 109 u8 logical_port_index;
110 u8 physical_port_index; 110 u8 physical_port_index;
111 u8 active_phy_mask; 111 u8 active_phy_mask;
112 u8 last_active_phy;
112 u16 reserved_rni; 113 u16 reserved_rni;
113 u16 reserved_tag; 114 u16 reserved_tag;
114 u32 started_request_count; 115 u32 started_request_count;