aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-02-23 04:12:10 -0500
committerDan Williams <dan.j.williams@intel.com>2012-05-17 15:27:12 -0400
commiteb608c3cb3f0a6b99252ea6a69fc0d2bbecf1f4f (patch)
treee28da3a8a530798c7c3368d16f88003ee3ee0643 /drivers
parentabec912d71c44bbd642ce12ad98aab76f5a53163 (diff)
isci: fix controller stop
1/ notify waiters when controller stop completes (fixes 10 second stall unloading the driver) 2/ make sure phy stop is after port and device stop Cc: Richard Boyd <richard.g.boyd@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/isci/host.c99
-rw-r--r--drivers/scsi/isci/host.h8
2 files changed, 55 insertions, 52 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index 0fe372f93289..95c3da66ea4b 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -1046,7 +1046,7 @@ void isci_host_scan_start(struct Scsi_Host *shost)
1046 spin_unlock_irq(&ihost->scic_lock); 1046 spin_unlock_irq(&ihost->scic_lock);
1047} 1047}
1048 1048
1049static void isci_host_stop_complete(struct isci_host *ihost, enum sci_status completion_status) 1049static void isci_host_stop_complete(struct isci_host *ihost)
1050{ 1050{
1051 sci_controller_disable_interrupts(ihost); 1051 sci_controller_disable_interrupts(ihost);
1052 clear_bit(IHOST_STOP_PENDING, &ihost->flags); 1052 clear_bit(IHOST_STOP_PENDING, &ihost->flags);
@@ -1232,7 +1232,7 @@ static enum sci_status sci_controller_reset(struct isci_host *ihost)
1232 switch (ihost->sm.current_state_id) { 1232 switch (ihost->sm.current_state_id) {
1233 case SCIC_RESET: 1233 case SCIC_RESET:
1234 case SCIC_READY: 1234 case SCIC_READY:
1235 case SCIC_STOPPED: 1235 case SCIC_STOPPING:
1236 case SCIC_FAILED: 1236 case SCIC_FAILED:
1237 /* 1237 /*
1238 * The reset operation is not a graceful cleanup, just 1238 * The reset operation is not a graceful cleanup, just
@@ -1247,6 +1247,44 @@ static enum sci_status sci_controller_reset(struct isci_host *ihost)
1247 } 1247 }
1248} 1248}
1249 1249
1250static enum sci_status sci_controller_stop_phys(struct isci_host *ihost)
1251{
1252 u32 index;
1253 enum sci_status status;
1254 enum sci_status phy_status;
1255
1256 status = SCI_SUCCESS;
1257
1258 for (index = 0; index < SCI_MAX_PHYS; index++) {
1259 phy_status = sci_phy_stop(&ihost->phys[index]);
1260
1261 if (phy_status != SCI_SUCCESS &&
1262 phy_status != SCI_FAILURE_INVALID_STATE) {
1263 status = SCI_FAILURE;
1264
1265 dev_warn(&ihost->pdev->dev,
1266 "%s: Controller stop operation failed to stop "
1267 "phy %d because of status %d.\n",
1268 __func__,
1269 ihost->phys[index].phy_index, phy_status);
1270 }
1271 }
1272
1273 return status;
1274}
1275
1276
1277/**
1278 * isci_host_deinit - shutdown frame reception and dma
1279 * @ihost: host to take down
1280 *
1281 * This is called in either the driver shutdown or the suspend path. In
1282 * the shutdown case libsas went through port teardown and normal device
1283 * removal (i.e. physical links stayed up to service scsi_device removal
1284 * commands). In the suspend case we disable the hardware without
1285 * notifying libsas of the link down events since we want libsas to
1286 * remember the domain across the suspend/resume cycle
1287 */
1250void isci_host_deinit(struct isci_host *ihost) 1288void isci_host_deinit(struct isci_host *ihost)
1251{ 1289{
1252 int i; 1290 int i;
@@ -1255,16 +1293,6 @@ void isci_host_deinit(struct isci_host *ihost)
1255 for (i = 0; i < isci_gpio_count(ihost); i++) 1293 for (i = 0; i < isci_gpio_count(ihost); i++)
1256 writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]); 1294 writel(SGPIO_HW_CONTROL, &ihost->scu_registers->peg0.sgpio.output_data_select[i]);
1257 1295
1258 for (i = 0; i < SCI_MAX_PORTS; i++) {
1259 struct isci_port *iport = &ihost->ports[i];
1260 struct isci_remote_device *idev, *d;
1261
1262 list_for_each_entry_safe(idev, d, &iport->remote_dev_list, node) {
1263 if (test_bit(IDEV_ALLOCATED, &idev->flags))
1264 isci_remote_device_stop(ihost, idev);
1265 }
1266 }
1267
1268 set_bit(IHOST_STOP_PENDING, &ihost->flags); 1296 set_bit(IHOST_STOP_PENDING, &ihost->flags);
1269 1297
1270 spin_lock_irq(&ihost->scic_lock); 1298 spin_lock_irq(&ihost->scic_lock);
@@ -1273,6 +1301,13 @@ void isci_host_deinit(struct isci_host *ihost)
1273 1301
1274 wait_for_stop(ihost); 1302 wait_for_stop(ihost);
1275 1303
1304 /* phy stop is after controller stop to allow port and device to
1305 * go idle before shutting down the phys, but the expectation is
1306 * that i/o has been shut off well before we reach this
1307 * function.
1308 */
1309 sci_controller_stop_phys(ihost);
1310
1276 /* disable sgpio: where the above wait should give time for the 1311 /* disable sgpio: where the above wait should give time for the
1277 * enclosure to sample the gpios going inactive 1312 * enclosure to sample the gpios going inactive
1278 */ 1313 */
@@ -1476,32 +1511,6 @@ static void sci_controller_ready_state_exit(struct sci_base_state_machine *sm)
1476 sci_controller_set_interrupt_coalescence(ihost, 0, 0); 1511 sci_controller_set_interrupt_coalescence(ihost, 0, 0);
1477} 1512}
1478 1513
1479static enum sci_status sci_controller_stop_phys(struct isci_host *ihost)
1480{
1481 u32 index;
1482 enum sci_status status;
1483 enum sci_status phy_status;
1484
1485 status = SCI_SUCCESS;
1486
1487 for (index = 0; index < SCI_MAX_PHYS; index++) {
1488 phy_status = sci_phy_stop(&ihost->phys[index]);
1489
1490 if (phy_status != SCI_SUCCESS &&
1491 phy_status != SCI_FAILURE_INVALID_STATE) {
1492 status = SCI_FAILURE;
1493
1494 dev_warn(&ihost->pdev->dev,
1495 "%s: Controller stop operation failed to stop "
1496 "phy %d because of status %d.\n",
1497 __func__,
1498 ihost->phys[index].phy_index, phy_status);
1499 }
1500 }
1501
1502 return status;
1503}
1504
1505static enum sci_status sci_controller_stop_ports(struct isci_host *ihost) 1514static enum sci_status sci_controller_stop_ports(struct isci_host *ihost)
1506{ 1515{
1507 u32 index; 1516 u32 index;
@@ -1561,10 +1570,11 @@ static void sci_controller_stopping_state_enter(struct sci_base_state_machine *s
1561{ 1570{
1562 struct isci_host *ihost = container_of(sm, typeof(*ihost), sm); 1571 struct isci_host *ihost = container_of(sm, typeof(*ihost), sm);
1563 1572
1564 /* Stop all of the components for this controller */
1565 sci_controller_stop_phys(ihost);
1566 sci_controller_stop_ports(ihost);
1567 sci_controller_stop_devices(ihost); 1573 sci_controller_stop_devices(ihost);
1574 sci_controller_stop_ports(ihost);
1575
1576 if (!sci_controller_has_remote_devices_stopping(ihost))
1577 isci_host_stop_complete(ihost);
1568} 1578}
1569 1579
1570static void sci_controller_stopping_state_exit(struct sci_base_state_machine *sm) 1580static void sci_controller_stopping_state_exit(struct sci_base_state_machine *sm)
@@ -1621,7 +1631,6 @@ static const struct sci_base_state sci_controller_state_table[] = {
1621 .enter_state = sci_controller_stopping_state_enter, 1631 .enter_state = sci_controller_stopping_state_enter,
1622 .exit_state = sci_controller_stopping_state_exit, 1632 .exit_state = sci_controller_stopping_state_exit,
1623 }, 1633 },
1624 [SCIC_STOPPED] = {},
1625 [SCIC_FAILED] = {} 1634 [SCIC_FAILED] = {}
1626}; 1635};
1627 1636
@@ -1641,7 +1650,7 @@ static void controller_timeout(unsigned long data)
1641 sci_controller_transition_to_ready(ihost, SCI_FAILURE_TIMEOUT); 1650 sci_controller_transition_to_ready(ihost, SCI_FAILURE_TIMEOUT);
1642 else if (sm->current_state_id == SCIC_STOPPING) { 1651 else if (sm->current_state_id == SCIC_STOPPING) {
1643 sci_change_state(sm, SCIC_FAILED); 1652 sci_change_state(sm, SCIC_FAILED);
1644 isci_host_stop_complete(ihost, SCI_FAILURE_TIMEOUT); 1653 isci_host_stop_complete(ihost);
1645 } else /* / @todo Now what do we want to do in this case? */ 1654 } else /* / @todo Now what do we want to do in this case? */
1646 dev_err(&ihost->pdev->dev, 1655 dev_err(&ihost->pdev->dev,
1647 "%s: Controller timer fired when controller was not " 1656 "%s: Controller timer fired when controller was not "
@@ -2452,7 +2461,7 @@ void sci_controller_link_down(struct isci_host *ihost, struct isci_port *iport,
2452 } 2461 }
2453} 2462}
2454 2463
2455static bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost) 2464bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost)
2456{ 2465{
2457 u32 index; 2466 u32 index;
2458 2467
@@ -2478,7 +2487,7 @@ void sci_controller_remote_device_stopped(struct isci_host *ihost,
2478 } 2487 }
2479 2488
2480 if (!sci_controller_has_remote_devices_stopping(ihost)) 2489 if (!sci_controller_has_remote_devices_stopping(ihost))
2481 sci_change_state(&ihost->sm, SCIC_STOPPED); 2490 isci_host_stop_complete(ihost);
2482} 2491}
2483 2492
2484void sci_controller_post_request(struct isci_host *ihost, u32 request) 2493void sci_controller_post_request(struct isci_host *ihost, u32 request)
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 4695162f406e..a89c0e3c5a14 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -277,13 +277,6 @@ enum sci_controller_states {
277 SCIC_STOPPING, 277 SCIC_STOPPING,
278 278
279 /** 279 /**
280 * This state indicates that the controller has successfully been stopped.
281 * In this state no new IO operations are permitted.
282 * This state is entered from the STOPPING state.
283 */
284 SCIC_STOPPED,
285
286 /**
287 * This state indicates that the controller could not successfully be 280 * This state indicates that the controller could not successfully be
288 * initialized. In this state no new IO operations are permitted. 281 * initialized. In this state no new IO operations are permitted.
289 * This state is entered from the INITIALIZING state. 282 * This state is entered from the INITIALIZING state.
@@ -479,6 +472,7 @@ int isci_host_init(struct isci_host *);
479void isci_host_completion_routine(unsigned long data); 472void isci_host_completion_routine(unsigned long data);
480void isci_host_deinit(struct isci_host *); 473void isci_host_deinit(struct isci_host *);
481void sci_controller_disable_interrupts(struct isci_host *ihost); 474void sci_controller_disable_interrupts(struct isci_host *ihost);
475bool sci_controller_has_remote_devices_stopping(struct isci_host *ihost);
482 476
483enum sci_status sci_controller_start_io( 477enum sci_status sci_controller_start_io(
484 struct isci_host *ihost, 478 struct isci_host *ihost,