aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/isci')
-rw-r--r--drivers/scsi/isci/port.c26
-rw-r--r--drivers/scsi/isci/port.h5
-rw-r--r--drivers/scsi/isci/remote_device.h7
-rw-r--r--drivers/scsi/isci/remote_node_context.c15
4 files changed, 51 insertions, 2 deletions
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 0a3aec118097..ed206c5a00a6 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -1548,6 +1548,29 @@ static void sci_port_failed_state_enter(struct sci_base_state_machine *sm)
1548 isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT); 1548 isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT);
1549} 1549}
1550 1550
1551void sci_port_set_hang_detection_timeout(struct isci_port *iport, u32 timeout)
1552{
1553 int phy_index;
1554 u32 phy_mask = iport->active_phy_mask;
1555
1556 if (timeout)
1557 ++iport->hang_detect_users;
1558 else if (iport->hang_detect_users > 1)
1559 --iport->hang_detect_users;
1560 else
1561 iport->hang_detect_users = 0;
1562
1563 if (timeout || (iport->hang_detect_users == 0)) {
1564 for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) {
1565 if ((phy_mask >> phy_index) & 1) {
1566 writel(timeout,
1567 &iport->phy_table[phy_index]
1568 ->link_layer_registers
1569 ->link_layer_hang_detection_timeout);
1570 }
1571 }
1572 }
1573}
1551/* --------------------------------------------------------------------------- */ 1574/* --------------------------------------------------------------------------- */
1552 1575
1553static const struct sci_base_state sci_port_state_table[] = { 1576static const struct sci_base_state sci_port_state_table[] = {
@@ -1596,6 +1619,7 @@ void sci_port_construct(struct isci_port *iport, u8 index,
1596 1619
1597 iport->started_request_count = 0; 1620 iport->started_request_count = 0;
1598 iport->assigned_device_count = 0; 1621 iport->assigned_device_count = 0;
1622 iport->hang_detect_users = 0;
1599 1623
1600 iport->reserved_rni = SCU_DUMMY_INDEX; 1624 iport->reserved_rni = SCU_DUMMY_INDEX;
1601 iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG; 1625 iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG;
@@ -1733,7 +1757,7 @@ void isci_port_formed(struct asd_sas_phy *phy)
1733 struct isci_host *ihost = phy->ha->lldd_ha; 1757 struct isci_host *ihost = phy->ha->lldd_ha;
1734 struct isci_phy *iphy = to_iphy(phy); 1758 struct isci_phy *iphy = to_iphy(phy);
1735 struct asd_sas_port *port = phy->port; 1759 struct asd_sas_port *port = phy->port;
1736 struct isci_port *iport; 1760 struct isci_port *iport = NULL;
1737 unsigned long flags; 1761 unsigned long flags;
1738 int i; 1762 int i;
1739 1763
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
index f8bd1e8dbfea..861e8f72811b 100644
--- a/drivers/scsi/isci/port.h
+++ b/drivers/scsi/isci/port.h
@@ -111,6 +111,7 @@ struct isci_port {
111 u16 reserved_tag; 111 u16 reserved_tag;
112 u32 started_request_count; 112 u32 started_request_count;
113 u32 assigned_device_count; 113 u32 assigned_device_count;
114 u32 hang_detect_users;
114 u32 not_ready_reason; 115 u32 not_ready_reason;
115 struct isci_phy *phy_table[SCI_MAX_PHYS]; 116 struct isci_phy *phy_table[SCI_MAX_PHYS];
116 struct isci_host *owning_controller; 117 struct isci_host *owning_controller;
@@ -269,6 +270,10 @@ void sci_port_get_attached_sas_address(
269 struct isci_port *iport, 270 struct isci_port *iport,
270 struct sci_sas_address *sas_address); 271 struct sci_sas_address *sas_address);
271 272
273void sci_port_set_hang_detection_timeout(
274 struct isci_port *isci_port,
275 u32 timeout);
276
272void isci_port_formed(struct asd_sas_phy *); 277void isci_port_formed(struct asd_sas_phy *);
273void isci_port_deformed(struct asd_sas_phy *); 278void isci_port_deformed(struct asd_sas_phy *);
274 279
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index 4a67ff0eb94e..4850b58edbe6 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -301,6 +301,13 @@ static inline void sci_remote_device_decrement_request_count(struct isci_remote_
301 idev->started_request_count--; 301 idev->started_request_count--;
302} 302}
303 303
304static inline void isci_dev_set_hang_detection_timeout(
305 struct isci_remote_device *idev,
306 u32 timeout)
307{
308 sci_port_set_hang_detection_timeout(idev->owning_port, timeout);
309}
310
304enum sci_status sci_remote_device_frame_handler( 311enum sci_status sci_remote_device_frame_handler(
305 struct isci_remote_device *idev, 312 struct isci_remote_device *idev,
306 u32 frame_index); 313 u32 frame_index);
diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c
index 8ce5a35891e1..3a55ba66b8ac 100644
--- a/drivers/scsi/isci/remote_node_context.c
+++ b/drivers/scsi/isci/remote_node_context.c
@@ -316,6 +316,15 @@ static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_
316 sci_remote_node_context_continue_state_transitions(rnc); 316 sci_remote_node_context_continue_state_transitions(rnc);
317} 317}
318 318
319static void sci_remote_node_context_await_suspend_state_exit(
320 struct sci_base_state_machine *sm)
321{
322 struct sci_remote_node_context *rnc
323 = container_of(sm, typeof(*rnc), sm);
324
325 isci_dev_set_hang_detection_timeout(rnc_to_dev(rnc), 0);
326}
327
319static const struct sci_base_state sci_remote_node_context_state_table[] = { 328static const struct sci_base_state sci_remote_node_context_state_table[] = {
320 [SCI_RNC_INITIAL] = { 329 [SCI_RNC_INITIAL] = {
321 .enter_state = sci_remote_node_context_initial_state_enter, 330 .enter_state = sci_remote_node_context_initial_state_enter,
@@ -338,7 +347,9 @@ static const struct sci_base_state sci_remote_node_context_state_table[] = {
338 [SCI_RNC_TX_RX_SUSPENDED] = { 347 [SCI_RNC_TX_RX_SUSPENDED] = {
339 .enter_state = sci_remote_node_context_tx_rx_suspended_state_enter, 348 .enter_state = sci_remote_node_context_tx_rx_suspended_state_enter,
340 }, 349 },
341 [SCI_RNC_AWAIT_SUSPENSION] = { }, 350 [SCI_RNC_AWAIT_SUSPENSION] = {
351 .exit_state = sci_remote_node_context_await_suspend_state_exit,
352 },
342}; 353};
343 354
344void sci_remote_node_context_construct(struct sci_remote_node_context *rnc, 355void sci_remote_node_context_construct(struct sci_remote_node_context *rnc,
@@ -513,6 +524,8 @@ enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *
513 if (suspend_type == SCI_SOFTWARE_SUSPENSION) { 524 if (suspend_type == SCI_SOFTWARE_SUSPENSION) {
514 sci_remote_device_post_request(rnc_to_dev(sci_rnc), 525 sci_remote_device_post_request(rnc_to_dev(sci_rnc),
515 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX); 526 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX);
527 isci_dev_set_hang_detection_timeout(rnc_to_dev(sci_rnc),
528 0x00000001);
516 } 529 }
517 530
518 sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION); 531 sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);