diff options
Diffstat (limited to 'drivers/scsi/isci/remote_device.c')
-rw-r--r-- | drivers/scsi/isci/remote_device.c | 80 |
1 files changed, 41 insertions, 39 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index 45592ad33c3b..ab5f9868e4ef 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c | |||
@@ -94,7 +94,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, | |||
94 | "%s: isci_device = %p\n", __func__, idev); | 94 | "%s: isci_device = %p\n", __func__, idev); |
95 | 95 | ||
96 | if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) | 96 | if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) |
97 | isci_remote_device_change_state(idev, isci_stopping); | 97 | set_bit(IDEV_GONE, &idev->flags); |
98 | else | 98 | else |
99 | /* device ready is actually a "not ready for io" state. */ | 99 | /* device ready is actually a "not ready for io" state. */ |
100 | isci_remote_device_change_state(idev, isci_ready); | 100 | isci_remote_device_change_state(idev, isci_ready); |
@@ -449,8 +449,10 @@ static void scic_sds_remote_device_start_request(struct scic_sds_remote_device * | |||
449 | /* cleanup requests that failed after starting on the port */ | 449 | /* cleanup requests that failed after starting on the port */ |
450 | if (status != SCI_SUCCESS) | 450 | if (status != SCI_SUCCESS) |
451 | scic_sds_port_complete_io(sci_port, sci_dev, sci_req); | 451 | scic_sds_port_complete_io(sci_port, sci_dev, sci_req); |
452 | else | 452 | else { |
453 | kref_get(&sci_dev_to_idev(sci_dev)->kref); | ||
453 | scic_sds_remote_device_increment_request_count(sci_dev); | 454 | scic_sds_remote_device_increment_request_count(sci_dev); |
455 | } | ||
454 | } | 456 | } |
455 | 457 | ||
456 | enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic, | 458 | enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic, |
@@ -656,6 +658,8 @@ enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *s | |||
656 | "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " | 658 | "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " |
657 | "could not complete\n", __func__, sci_port, | 659 | "could not complete\n", __func__, sci_port, |
658 | sci_dev, sci_req, status); | 660 | sci_dev, sci_req, status); |
661 | else | ||
662 | isci_put_device(sci_dev_to_idev(sci_dev)); | ||
659 | 663 | ||
660 | return status; | 664 | return status; |
661 | } | 665 | } |
@@ -860,23 +864,11 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_ | |||
860 | * here should go through isci_remote_device_nuke_requests. | 864 | * here should go through isci_remote_device_nuke_requests. |
861 | * If we hit this condition, we will need a way to complete | 865 | * If we hit this condition, we will need a way to complete |
862 | * io requests in process */ | 866 | * io requests in process */ |
863 | while (!list_empty(&idev->reqs_in_process)) { | 867 | BUG_ON(!list_empty(&idev->reqs_in_process)); |
864 | |||
865 | dev_err(&ihost->pdev->dev, | ||
866 | "%s: ** request list not empty! **\n", __func__); | ||
867 | BUG(); | ||
868 | } | ||
869 | 868 | ||
870 | scic_remote_device_destruct(&idev->sci); | 869 | scic_remote_device_destruct(&idev->sci); |
871 | idev->domain_dev->lldd_dev = NULL; | ||
872 | idev->domain_dev = NULL; | ||
873 | idev->isci_port = NULL; | ||
874 | list_del_init(&idev->node); | 870 | list_del_init(&idev->node); |
875 | 871 | isci_put_device(idev); | |
876 | clear_bit(IDEV_START_PENDING, &idev->flags); | ||
877 | clear_bit(IDEV_STOP_PENDING, &idev->flags); | ||
878 | clear_bit(IDEV_EH, &idev->flags); | ||
879 | wake_up(&ihost->eventq); | ||
880 | } | 872 | } |
881 | 873 | ||
882 | /** | 874 | /** |
@@ -1314,6 +1306,22 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) | |||
1314 | return idev; | 1306 | return idev; |
1315 | } | 1307 | } |
1316 | 1308 | ||
1309 | void isci_remote_device_release(struct kref *kref) | ||
1310 | { | ||
1311 | struct isci_remote_device *idev = container_of(kref, typeof(*idev), kref); | ||
1312 | struct isci_host *ihost = idev->isci_port->isci_host; | ||
1313 | |||
1314 | idev->domain_dev = NULL; | ||
1315 | idev->isci_port = NULL; | ||
1316 | clear_bit(IDEV_START_PENDING, &idev->flags); | ||
1317 | clear_bit(IDEV_STOP_PENDING, &idev->flags); | ||
1318 | clear_bit(IDEV_GONE, &idev->flags); | ||
1319 | clear_bit(IDEV_EH, &idev->flags); | ||
1320 | smp_mb__before_clear_bit(); | ||
1321 | clear_bit(IDEV_ALLOCATED, &idev->flags); | ||
1322 | wake_up(&ihost->eventq); | ||
1323 | } | ||
1324 | |||
1317 | /** | 1325 | /** |
1318 | * isci_remote_device_stop() - This function is called internally to stop the | 1326 | * isci_remote_device_stop() - This function is called internally to stop the |
1319 | * remote device. | 1327 | * remote device. |
@@ -1330,7 +1338,11 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem | |||
1330 | dev_dbg(&ihost->pdev->dev, | 1338 | dev_dbg(&ihost->pdev->dev, |
1331 | "%s: isci_device = %p\n", __func__, idev); | 1339 | "%s: isci_device = %p\n", __func__, idev); |
1332 | 1340 | ||
1341 | spin_lock_irqsave(&ihost->scic_lock, flags); | ||
1342 | idev->domain_dev->lldd_dev = NULL; /* disable new lookups */ | ||
1343 | set_bit(IDEV_GONE, &idev->flags); | ||
1333 | isci_remote_device_change_state(idev, isci_stopping); | 1344 | isci_remote_device_change_state(idev, isci_stopping); |
1345 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | ||
1334 | 1346 | ||
1335 | /* Kill all outstanding requests. */ | 1347 | /* Kill all outstanding requests. */ |
1336 | isci_remote_device_nuke_requests(ihost, idev); | 1348 | isci_remote_device_nuke_requests(ihost, idev); |
@@ -1342,14 +1354,10 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem | |||
1342 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 1354 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
1343 | 1355 | ||
1344 | /* Wait for the stop complete callback. */ | 1356 | /* Wait for the stop complete callback. */ |
1345 | if (status == SCI_SUCCESS) { | 1357 | if (WARN_ONCE(status != SCI_SUCCESS, "failed to stop device\n")) |
1358 | /* nothing to wait for */; | ||
1359 | else | ||
1346 | wait_for_device_stop(ihost, idev); | 1360 | wait_for_device_stop(ihost, idev); |
1347 | clear_bit(IDEV_ALLOCATED, &idev->flags); | ||
1348 | } | ||
1349 | |||
1350 | dev_dbg(&ihost->pdev->dev, | ||
1351 | "%s: idev = %p - after completion wait\n", | ||
1352 | __func__, idev); | ||
1353 | 1361 | ||
1354 | return status; | 1362 | return status; |
1355 | } | 1363 | } |
@@ -1416,39 +1424,33 @@ int isci_remote_device_found(struct domain_device *domain_dev) | |||
1416 | if (!isci_device) | 1424 | if (!isci_device) |
1417 | return -ENODEV; | 1425 | return -ENODEV; |
1418 | 1426 | ||
1427 | kref_init(&isci_device->kref); | ||
1419 | INIT_LIST_HEAD(&isci_device->node); | 1428 | INIT_LIST_HEAD(&isci_device->node); |
1420 | domain_dev->lldd_dev = isci_device; | 1429 | |
1430 | spin_lock_irq(&isci_host->scic_lock); | ||
1421 | isci_device->domain_dev = domain_dev; | 1431 | isci_device->domain_dev = domain_dev; |
1422 | isci_device->isci_port = isci_port; | 1432 | isci_device->isci_port = isci_port; |
1423 | isci_remote_device_change_state(isci_device, isci_starting); | 1433 | isci_remote_device_change_state(isci_device, isci_starting); |
1424 | |||
1425 | |||
1426 | spin_lock_irq(&isci_host->scic_lock); | ||
1427 | list_add_tail(&isci_device->node, &isci_port->remote_dev_list); | 1434 | list_add_tail(&isci_device->node, &isci_port->remote_dev_list); |
1428 | 1435 | ||
1429 | set_bit(IDEV_START_PENDING, &isci_device->flags); | 1436 | set_bit(IDEV_START_PENDING, &isci_device->flags); |
1430 | status = isci_remote_device_construct(isci_port, isci_device); | 1437 | status = isci_remote_device_construct(isci_port, isci_device); |
1431 | spin_unlock_irq(&isci_host->scic_lock); | ||
1432 | 1438 | ||
1433 | dev_dbg(&isci_host->pdev->dev, | 1439 | dev_dbg(&isci_host->pdev->dev, |
1434 | "%s: isci_device = %p\n", | 1440 | "%s: isci_device = %p\n", |
1435 | __func__, isci_device); | 1441 | __func__, isci_device); |
1436 | 1442 | ||
1437 | if (status != SCI_SUCCESS) { | 1443 | if (status == SCI_SUCCESS) { |
1438 | 1444 | /* device came up, advertise it to the world */ | |
1439 | spin_lock_irq(&isci_host->scic_lock); | 1445 | domain_dev->lldd_dev = isci_device; |
1440 | isci_remote_device_deconstruct( | 1446 | } else |
1441 | isci_host, | 1447 | isci_put_device(isci_device); |
1442 | isci_device | 1448 | spin_unlock_irq(&isci_host->scic_lock); |
1443 | ); | ||
1444 | spin_unlock_irq(&isci_host->scic_lock); | ||
1445 | return -ENODEV; | ||
1446 | } | ||
1447 | 1449 | ||
1448 | /* wait for the device ready callback. */ | 1450 | /* wait for the device ready callback. */ |
1449 | wait_for_device_start(isci_host, isci_device); | 1451 | wait_for_device_start(isci_host, isci_device); |
1450 | 1452 | ||
1451 | return 0; | 1453 | return status == SCI_SUCCESS ? 0 : -ENODEV; |
1452 | } | 1454 | } |
1453 | /** | 1455 | /** |
1454 | * isci_device_is_reset_pending() - This function will check if there is any | 1456 | * isci_device_is_reset_pending() - This function will check if there is any |