diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-06-16 14:26:12 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 07:04:51 -0400 |
commit | f2088267514b39af1a94409168101527769a911c (patch) | |
tree | 9155ce7eb3edf40ecdabc690bff34622ecea1294 /drivers/scsi/isci/remote_device.c | |
parent | 209fae14fabfd48525e5630bebbbd4ca15090c60 (diff) |
isci: kill isci_remote_device_change_state()
Now that "stopping/stopped" are one in the same and signalled by a NULL device
pointer the rest of the device status infrastructure can be removed (->status
and ->state_lock). The "not ready for i/o state" is replaced with a state
flag, and is evaluated under scic_lock so that we don't see transients from
taking the device reference to submitting the i/o.
This also fixes a potential leakage of can_queue slots in the rare case that
SAS_TASK_ABORTED is set at submission.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/remote_device.c')
-rw-r--r-- | drivers/scsi/isci/remote_device.c | 50 |
1 files changed, 4 insertions, 46 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index ab5f9868e4ef..c2e5c05be0cb 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c | |||
@@ -62,24 +62,6 @@ | |||
62 | #include "task.h" | 62 | #include "task.h" |
63 | 63 | ||
64 | /** | 64 | /** |
65 | * isci_remote_device_change_state() - This function gets the status of the | ||
66 | * remote_device object. | ||
67 | * @isci_device: This parameter points to the isci_remote_device object | ||
68 | * | ||
69 | * status of the object as a isci_status enum. | ||
70 | */ | ||
71 | void isci_remote_device_change_state( | ||
72 | struct isci_remote_device *isci_device, | ||
73 | enum isci_status status) | ||
74 | { | ||
75 | unsigned long flags; | ||
76 | |||
77 | spin_lock_irqsave(&isci_device->state_lock, flags); | ||
78 | isci_device->status = status; | ||
79 | spin_unlock_irqrestore(&isci_device->state_lock, flags); | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * isci_remote_device_not_ready() - This function is called by the scic when | 65 | * isci_remote_device_not_ready() - This function is called by the scic when |
84 | * the remote device is not ready. We mark the isci device as ready (not | 66 | * the remote device is not ready. We mark the isci device as ready (not |
85 | * "ready_for_io") and signal the waiting proccess. | 67 | * "ready_for_io") and signal the waiting proccess. |
@@ -96,8 +78,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, | |||
96 | if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) | 78 | if (reason == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) |
97 | set_bit(IDEV_GONE, &idev->flags); | 79 | set_bit(IDEV_GONE, &idev->flags); |
98 | else | 80 | else |
99 | /* device ready is actually a "not ready for io" state. */ | 81 | clear_bit(IDEV_IO_READY, &idev->flags); |
100 | isci_remote_device_change_state(idev, isci_ready); | ||
101 | } | 82 | } |
102 | 83 | ||
103 | /** | 84 | /** |
@@ -113,7 +94,7 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote | |||
113 | dev_dbg(&ihost->pdev->dev, | 94 | dev_dbg(&ihost->pdev->dev, |
114 | "%s: idev = %p\n", __func__, idev); | 95 | "%s: idev = %p\n", __func__, idev); |
115 | 96 | ||
116 | isci_remote_device_change_state(idev, isci_ready_for_io); | 97 | set_bit(IDEV_IO_READY, &idev->flags); |
117 | if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags)) | 98 | if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags)) |
118 | wake_up(&ihost->eventq); | 99 | wake_up(&ihost->eventq); |
119 | } | 100 | } |
@@ -871,26 +852,6 @@ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_ | |||
871 | isci_put_device(idev); | 852 | isci_put_device(idev); |
872 | } | 853 | } |
873 | 854 | ||
874 | /** | ||
875 | * isci_remote_device_stop_complete() - This function is called by the scic | ||
876 | * when the remote device stop has completed. We mark the isci device as not | ||
877 | * ready and remove the isci remote device. | ||
878 | * @ihost: This parameter specifies the isci host object. | ||
879 | * @idev: This parameter specifies the remote device. | ||
880 | * @status: This parameter specifies status of the completion. | ||
881 | * | ||
882 | */ | ||
883 | static void isci_remote_device_stop_complete(struct isci_host *ihost, | ||
884 | struct isci_remote_device *idev) | ||
885 | { | ||
886 | dev_dbg(&ihost->pdev->dev, "%s: complete idev = %p\n", __func__, idev); | ||
887 | |||
888 | isci_remote_device_change_state(idev, isci_stopped); | ||
889 | |||
890 | /* after stop, we can tear down resources. */ | ||
891 | isci_remote_device_deconstruct(ihost, idev); | ||
892 | } | ||
893 | |||
894 | static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_machine *sm) | 855 | static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_machine *sm) |
895 | { | 856 | { |
896 | struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); | 857 | struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm); |
@@ -903,7 +864,7 @@ static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_mac | |||
903 | */ | 864 | */ |
904 | prev_state = sci_dev->sm.previous_state_id; | 865 | prev_state = sci_dev->sm.previous_state_id; |
905 | if (prev_state == SCI_DEV_STOPPING) | 866 | if (prev_state == SCI_DEV_STOPPING) |
906 | isci_remote_device_stop_complete(scic_to_ihost(scic), idev); | 867 | isci_remote_device_deconstruct(scic_to_ihost(scic), idev); |
907 | 868 | ||
908 | scic_sds_controller_remote_device_stopped(scic, sci_dev); | 869 | scic_sds_controller_remote_device_stopped(scic, sci_dev); |
909 | } | 870 | } |
@@ -1301,8 +1262,6 @@ isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) | |||
1301 | if (WARN_ONCE(!list_empty(&idev->node), "found non-idle remote device\n")) | 1262 | if (WARN_ONCE(!list_empty(&idev->node), "found non-idle remote device\n")) |
1302 | return NULL; | 1263 | return NULL; |
1303 | 1264 | ||
1304 | isci_remote_device_change_state(idev, isci_freed); | ||
1305 | |||
1306 | return idev; | 1265 | return idev; |
1307 | } | 1266 | } |
1308 | 1267 | ||
@@ -1315,6 +1274,7 @@ void isci_remote_device_release(struct kref *kref) | |||
1315 | idev->isci_port = NULL; | 1274 | idev->isci_port = NULL; |
1316 | clear_bit(IDEV_START_PENDING, &idev->flags); | 1275 | clear_bit(IDEV_START_PENDING, &idev->flags); |
1317 | clear_bit(IDEV_STOP_PENDING, &idev->flags); | 1276 | clear_bit(IDEV_STOP_PENDING, &idev->flags); |
1277 | clear_bit(IDEV_IO_READY, &idev->flags); | ||
1318 | clear_bit(IDEV_GONE, &idev->flags); | 1278 | clear_bit(IDEV_GONE, &idev->flags); |
1319 | clear_bit(IDEV_EH, &idev->flags); | 1279 | clear_bit(IDEV_EH, &idev->flags); |
1320 | smp_mb__before_clear_bit(); | 1280 | smp_mb__before_clear_bit(); |
@@ -1341,7 +1301,6 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem | |||
1341 | spin_lock_irqsave(&ihost->scic_lock, flags); | 1301 | spin_lock_irqsave(&ihost->scic_lock, flags); |
1342 | idev->domain_dev->lldd_dev = NULL; /* disable new lookups */ | 1302 | idev->domain_dev->lldd_dev = NULL; /* disable new lookups */ |
1343 | set_bit(IDEV_GONE, &idev->flags); | 1303 | set_bit(IDEV_GONE, &idev->flags); |
1344 | isci_remote_device_change_state(idev, isci_stopping); | ||
1345 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 1304 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
1346 | 1305 | ||
1347 | /* Kill all outstanding requests. */ | 1306 | /* Kill all outstanding requests. */ |
@@ -1430,7 +1389,6 @@ int isci_remote_device_found(struct domain_device *domain_dev) | |||
1430 | spin_lock_irq(&isci_host->scic_lock); | 1389 | spin_lock_irq(&isci_host->scic_lock); |
1431 | isci_device->domain_dev = domain_dev; | 1390 | isci_device->domain_dev = domain_dev; |
1432 | isci_device->isci_port = isci_port; | 1391 | isci_device->isci_port = isci_port; |
1433 | isci_remote_device_change_state(isci_device, isci_starting); | ||
1434 | list_add_tail(&isci_device->node, &isci_port->remote_dev_list); | 1392 | list_add_tail(&isci_device->node, &isci_port->remote_dev_list); |
1435 | 1393 | ||
1436 | set_bit(IDEV_START_PENDING, &isci_device->flags); | 1394 | set_bit(IDEV_START_PENDING, &isci_device->flags); |