aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;