diff options
Diffstat (limited to 'drivers/scsi/isci')
-rw-r--r-- | drivers/scsi/isci/port.c | 26 | ||||
-rw-r--r-- | drivers/scsi/isci/port.h | 5 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_device.h | 7 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_node_context.c | 15 |
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 | ||
1551 | void 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 | ||
1553 | static const struct sci_base_state sci_port_state_table[] = { | 1576 | static 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 | ||
273 | void sci_port_set_hang_detection_timeout( | ||
274 | struct isci_port *isci_port, | ||
275 | u32 timeout); | ||
276 | |||
272 | void isci_port_formed(struct asd_sas_phy *); | 277 | void isci_port_formed(struct asd_sas_phy *); |
273 | void isci_port_deformed(struct asd_sas_phy *); | 278 | void 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 | ||
304 | static 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 | |||
304 | enum sci_status sci_remote_device_frame_handler( | 311 | enum 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 | ||
319 | static 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 | |||
319 | static const struct sci_base_state sci_remote_node_context_state_table[] = { | 328 | static 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 | ||
344 | void sci_remote_node_context_construct(struct sci_remote_node_context *rnc, | 355 | void 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); |