aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/remote_device.c
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2012-03-09 01:41:54 -0500
committerDan Williams <dan.j.williams@intel.com>2012-05-17 17:33:38 -0400
commit14aaa9f0a318bd04cbb9d822524b817e95d8b343 (patch)
tree5f6292ec671d0993c1df51586dea4fb7750d1cd9 /drivers/scsi/isci/remote_device.c
parentd80ecd5726ce49b5da457d562804b40f0183e8f7 (diff)
isci: Redesign device suspension, abort, cleanup.
This commit changes the means by which outstanding I/Os are handled for cleanup. The likelihood is that this commit will be broken into smaller pieces, however that will be a later revision. Among the changes: - All completion structures have been removed from the tmf and abort paths. - Now using one completed I/O list, with the I/O completed in host bit being used to select error or normal callback paths. Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com> 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.c255
1 files changed, 119 insertions, 136 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index 3048e02aeb7b..c47304cea45d 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -81,49 +81,6 @@ static enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev
81} 81}
82 82
83/** 83/**
84 * isci_remote_device_not_ready() - This function is called by the ihost when
85 * the remote device is not ready. We mark the isci device as ready (not
86 * "ready_for_io") and signal the waiting proccess.
87 * @isci_host: This parameter specifies the isci host object.
88 * @isci_device: This parameter specifies the remote device
89 *
90 * sci_lock is held on entrance to this function.
91 */
92static void isci_remote_device_not_ready(struct isci_host *ihost,
93 struct isci_remote_device *idev, u32 reason)
94{
95 struct isci_request *ireq;
96
97 dev_dbg(&ihost->pdev->dev,
98 "%s: isci_device = %p\n", __func__, idev);
99
100 switch (reason) {
101 case SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED:
102 set_bit(IDEV_GONE, &idev->flags);
103 break;
104 case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED:
105 set_bit(IDEV_IO_NCQERROR, &idev->flags);
106
107 /* Suspend the remote device so the I/O can be terminated. */
108 sci_remote_device_suspend(idev);
109
110 /* Kill all outstanding requests for the device. */
111 list_for_each_entry(ireq, &idev->reqs_in_process, dev_node) {
112
113 dev_dbg(&ihost->pdev->dev,
114 "%s: isci_device = %p request = %p\n",
115 __func__, idev, ireq);
116
117 sci_controller_terminate_request(ihost, idev, ireq);
118 }
119 /* Fall through into the default case... */
120 default:
121 clear_bit(IDEV_IO_READY, &idev->flags);
122 break;
123 }
124}
125
126/**
127 * isci_remote_device_ready() - This function is called by the ihost when the 84 * isci_remote_device_ready() - This function is called by the ihost when the
128 * remote device is ready. We mark the isci device as ready and signal the 85 * remote device is ready. We mark the isci device as ready and signal the
129 * waiting proccess. 86 * waiting proccess.
@@ -142,49 +99,121 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote
142 wake_up(&ihost->eventq); 99 wake_up(&ihost->eventq);
143} 100}
144 101
145static int isci_remote_device_suspendcheck(struct isci_remote_device *idev) 102static enum sci_status sci_remote_device_terminate_req(
103 struct isci_host *ihost,
104 struct isci_remote_device *idev,
105 int check_abort,
106 struct isci_request *ireq)
107{
108 dev_dbg(&ihost->pdev->dev,
109 "%s: idev=%p; flags=%lx; req=%p; req target=%p\n",
110 __func__, idev, idev->flags, ireq, ireq->target_device);
111
112 if (!test_bit(IREQ_ACTIVE, &ireq->flags) ||
113 (ireq->target_device != idev) ||
114 (check_abort && !test_bit(IREQ_PENDING_ABORT, &ireq->flags)))
115 return SCI_SUCCESS;
116
117 set_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags);
118
119 return sci_controller_terminate_request(ihost, idev, ireq);
120}
121
122static enum sci_status sci_remote_device_terminate_reqs_checkabort(
123 struct isci_remote_device *idev,
124 int chk)
146{ 125{
147 return test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) 126 struct isci_host *ihost = idev->owning_port->owning_controller;
148 || !test_bit(IDEV_ALLOCATED, &idev->flags); 127 enum sci_status status = SCI_SUCCESS;
128 u32 i;
129
130 for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) {
131 struct isci_request *ireq = ihost->reqs[i];
132 enum sci_status s;
133
134 s = sci_remote_device_terminate_req(ihost, idev, chk, ireq);
135 if (s != SCI_SUCCESS)
136 status = s;
137 }
138 return status;
149} 139}
150 140
151enum sci_status isci_remote_device_suspend( 141enum sci_status isci_remote_device_terminate_requests(
152 struct isci_host *ihost, 142 struct isci_host *ihost,
153 struct isci_remote_device *idev) 143 struct isci_remote_device *idev,
144 struct isci_request *ireq)
154{ 145{
155 enum sci_status status; 146 enum sci_status status = SCI_SUCCESS;
156 unsigned long flags; 147 unsigned long flags;
157 148
158 spin_lock_irqsave(&ihost->scic_lock, flags); 149 spin_lock_irqsave(&ihost->scic_lock, flags);
159 if (isci_get_device(idev->domain_dev) == NULL) { 150 if (isci_get_device(idev) == NULL) {
151 dev_dbg(&ihost->pdev->dev, "%s: failed isci_get_device(idev=%p)\n",
152 __func__, idev);
160 spin_unlock_irqrestore(&ihost->scic_lock, flags); 153 spin_unlock_irqrestore(&ihost->scic_lock, flags);
161 status = SCI_FAILURE; 154 status = SCI_FAILURE;
162 } else { 155 } else {
163 status = sci_remote_device_suspend(idev); 156 dev_dbg(&ihost->pdev->dev,
164 spin_unlock_irqrestore(&ihost->scic_lock, flags); 157 "%s: idev=%p, ireq=%p; started_request_count=%d, "
165 if (status == SCI_SUCCESS) { 158 "about to wait\n",
166 dev_dbg(&ihost->pdev->dev, 159 __func__, idev, ireq, idev->started_request_count);
167 "%s: idev=%p, about to wait\n", 160 if (ireq) {
168 __func__, idev); 161 /* Terminate a specific TC. */
169 wait_event(ihost->eventq, 162 sci_remote_device_terminate_req(ihost, idev, 0, ireq);
170 isci_remote_device_suspendcheck(idev)); 163 spin_unlock_irqrestore(&ihost->scic_lock, flags);
171 status = test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) 164 wait_event(ihost->eventq, !test_bit(IREQ_ACTIVE,
172 ? SCI_SUCCESS : SCI_FAILURE; 165 &ireq->flags));
173 dev_dbg(&ihost->pdev->dev,
174 "%s: idev=%p, wait done, device is %s\n",
175 __func__, idev,
176 test_bit(IDEV_TXRX_SUSPENDED, &idev->flags)
177 ? "<suspended>" : "<deallocated!>");
178 166
179 } else 167 } else {
180 dev_dbg(scirdev_to_dev(idev), 168 /* Terminate all TCs. */
181 "%s: sci_remote_device_suspend failed, " 169 sci_remote_device_terminate_requests(idev);
182 "status = %d\n", __func__, status); 170 spin_unlock_irqrestore(&ihost->scic_lock, flags);
171 wait_event(ihost->eventq,
172 idev->started_request_count == 0);
173 }
174 dev_dbg(&ihost->pdev->dev, "%s: idev=%p, wait done\n",
175 __func__, idev);
183 isci_put_device(idev); 176 isci_put_device(idev);
184 } 177 }
185 return status; 178 return status;
186} 179}
187 180
181/**
182* isci_remote_device_not_ready() - This function is called by the ihost when
183* the remote device is not ready. We mark the isci device as ready (not
184* "ready_for_io") and signal the waiting proccess.
185* @isci_host: This parameter specifies the isci host object.
186* @isci_device: This parameter specifies the remote device
187*
188* sci_lock is held on entrance to this function.
189*/
190static void isci_remote_device_not_ready(struct isci_host *ihost,
191 struct isci_remote_device *idev,
192 u32 reason)
193{
194 dev_dbg(&ihost->pdev->dev,
195 "%s: isci_device = %p\n", __func__, idev);
196
197 switch (reason) {
198 case SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED:
199 set_bit(IDEV_GONE, &idev->flags);
200 break;
201 case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED:
202 set_bit(IDEV_IO_NCQERROR, &idev->flags);
203
204 /* Suspend the remote device so the I/O can be terminated. */
205 sci_remote_device_suspend(idev);
206
207 /* Kill all outstanding requests for the device. */
208 sci_remote_device_terminate_requests(idev);
209
210 /* Fall through into the default case... */
211 default:
212 clear_bit(IDEV_IO_READY, &idev->flags);
213 break;
214 }
215}
216
188/* called once the remote node context is ready to be freed. 217/* called once the remote node context is ready to be freed.
189 * The remote device can now report that its stop operation is complete. none 218 * The remote device can now report that its stop operation is complete. none
190 */ 219 */
@@ -196,36 +225,10 @@ static void rnc_destruct_done(void *_dev)
196 sci_change_state(&idev->sm, SCI_DEV_STOPPED); 225 sci_change_state(&idev->sm, SCI_DEV_STOPPED);
197} 226}
198 227
199static enum sci_status sci_remote_device_terminate_requests_checkabort(
200 struct isci_remote_device *idev,
201 int check_abort_pending)
202{
203 struct isci_host *ihost = idev->owning_port->owning_controller;
204 enum sci_status status = SCI_SUCCESS;
205 u32 i;
206
207 for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) {
208 struct isci_request *ireq = ihost->reqs[i];
209 enum sci_status s;
210
211 if (!test_bit(IREQ_ACTIVE, &ireq->flags) ||
212 (ireq->target_device != idev) ||
213 (check_abort_pending && !test_bit(IREQ_PENDING_ABORT,
214 &ireq->flags)))
215 continue;
216
217 s = sci_controller_terminate_request(ihost, idev, ireq);
218 if (s != SCI_SUCCESS)
219 status = s;
220 }
221
222 return status;
223}
224
225enum sci_status sci_remote_device_terminate_requests( 228enum sci_status sci_remote_device_terminate_requests(
226 struct isci_remote_device *idev) 229 struct isci_remote_device *idev)
227{ 230{
228 return sci_remote_device_terminate_requests_checkabort(idev, 0); 231 return sci_remote_device_terminate_reqs_checkabort(idev, 0);
229} 232}
230 233
231enum sci_status sci_remote_device_stop(struct isci_remote_device *idev, 234enum sci_status sci_remote_device_stop(struct isci_remote_device *idev,
@@ -771,10 +774,6 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
771 if (status != SCI_SUCCESS) 774 if (status != SCI_SUCCESS)
772 return status; 775 return status;
773 776
774 status = sci_remote_node_context_start_task(&idev->rnc, ireq);
775 if (status != SCI_SUCCESS)
776 goto out;
777
778 status = sci_request_start(ireq); 777 status = sci_request_start(ireq);
779 if (status != SCI_SUCCESS) 778 if (status != SCI_SUCCESS)
780 goto out; 779 goto out;
@@ -796,8 +795,9 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
796 sci_remote_node_context_suspend( 795 sci_remote_node_context_suspend(
797 &idev->rnc, SCI_SOFTWARE_SUSPENSION, 796 &idev->rnc, SCI_SOFTWARE_SUSPENSION,
798 SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL); 797 SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL);
799 sci_remote_node_context_resume( 798
800 &idev->rnc, sci_remote_device_continue_request, idev); 799 status = sci_remote_node_context_start_task(&idev->rnc, ireq,
800 sci_remote_device_continue_request, idev);
801 801
802 out: 802 out:
803 sci_remote_device_start_request(idev, ireq, status); 803 sci_remote_device_start_request(idev, ireq, status);
@@ -811,7 +811,9 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
811 if (status != SCI_SUCCESS) 811 if (status != SCI_SUCCESS)
812 return status; 812 return status;
813 813
814 status = sci_remote_node_context_start_task(&idev->rnc, ireq); 814 /* Resume the RNC as needed: */
815 status = sci_remote_node_context_start_task(&idev->rnc, ireq,
816 NULL, NULL);
815 if (status != SCI_SUCCESS) 817 if (status != SCI_SUCCESS)
816 break; 818 break;
817 819
@@ -1322,20 +1324,6 @@ static enum sci_status isci_remote_device_construct(struct isci_port *iport,
1322 return status; 1324 return status;
1323} 1325}
1324 1326
1325void isci_remote_device_nuke_requests(struct isci_host *ihost, struct isci_remote_device *idev)
1326{
1327 DECLARE_COMPLETION_ONSTACK(aborted_task_completion);
1328
1329 dev_dbg(&ihost->pdev->dev,
1330 "%s: idev = %p\n", __func__, idev);
1331
1332 /* Cleanup all requests pending for this device. */
1333 isci_terminate_pending_requests(ihost, idev);
1334
1335 dev_dbg(&ihost->pdev->dev,
1336 "%s: idev = %p, done\n", __func__, idev);
1337}
1338
1339/** 1327/**
1340 * This function builds the isci_remote_device when a libsas dev_found message 1328 * This function builds the isci_remote_device when a libsas dev_found message
1341 * is received. 1329 * is received.
@@ -1495,32 +1483,28 @@ int isci_remote_device_found(struct domain_device *dev)
1495 return status == SCI_SUCCESS ? 0 : -ENODEV; 1483 return status == SCI_SUCCESS ? 0 : -ENODEV;
1496} 1484}
1497 1485
1498enum sci_status isci_remote_device_reset( 1486enum sci_status isci_remote_device_suspend_terminate(
1499 struct isci_host *ihost, 1487 struct isci_host *ihost,
1500 struct isci_remote_device *idev) 1488 struct isci_remote_device *idev,
1489 struct isci_request *ireq)
1501{ 1490{
1502 unsigned long flags; 1491 unsigned long flags;
1503 enum sci_status status; 1492 enum sci_status status;
1504 1493
1505 /* Put the device into a reset state so the suspension will not 1494 /* Put the device into suspension. */
1506 * automatically resume.
1507 */
1508 spin_lock_irqsave(&ihost->scic_lock, flags); 1495 spin_lock_irqsave(&ihost->scic_lock, flags);
1509 status = sci_remote_device_reset(idev); 1496 sci_remote_device_suspend(idev);
1510 spin_unlock_irqrestore(&ihost->scic_lock, flags); 1497 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1511 if (status != SCI_SUCCESS) { 1498
1512 dev_dbg(&ihost->pdev->dev, 1499 /* Terminate and wait for the completions. */
1513 "%s: sci_remote_device_reset(%p) returned %d!\n", 1500 status = isci_remote_device_terminate_requests(ihost, idev, ireq);
1514 __func__, idev, status); 1501 if (status != SCI_SUCCESS)
1515 return status;
1516 }
1517 /* Wait for the device suspend. */
1518 status = isci_remote_device_suspend(ihost, idev);
1519 if (status != SCI_SUCCESS) {
1520 dev_dbg(&ihost->pdev->dev, 1502 dev_dbg(&ihost->pdev->dev,
1521 "%s: isci_remote_device_suspend(%p) returned %d!\n", 1503 "%s: isci_remote_device_terminate_requests(%p) "
1504 "returned %d!\n",
1522 __func__, idev, status); 1505 __func__, idev, status);
1523 } 1506
1507 /* NOTE: RNC resumption is left to the caller! */
1524 return status; 1508 return status;
1525} 1509}
1526 1510
@@ -1533,7 +1517,7 @@ int isci_remote_device_is_safe_to_abort(
1533enum sci_status sci_remote_device_abort_requests_pending_abort( 1517enum sci_status sci_remote_device_abort_requests_pending_abort(
1534 struct isci_remote_device *idev) 1518 struct isci_remote_device *idev)
1535{ 1519{
1536 return sci_remote_device_terminate_requests_checkabort(idev, 1); 1520 return sci_remote_device_terminate_reqs_checkabort(idev, 1);
1537} 1521}
1538 1522
1539enum sci_status isci_remote_device_reset_complete( 1523enum sci_status isci_remote_device_reset_complete(
@@ -1545,7 +1529,6 @@ enum sci_status isci_remote_device_reset_complete(
1545 1529
1546 spin_lock_irqsave(&ihost->scic_lock, flags); 1530 spin_lock_irqsave(&ihost->scic_lock, flags);
1547 status = sci_remote_device_reset_complete(idev); 1531 status = sci_remote_device_reset_complete(idev);
1548 sci_remote_device_resume(idev, NULL, NULL);
1549 spin_unlock_irqrestore(&ihost->scic_lock, flags); 1532 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1550 1533
1551 return status; 1534 return status;