blob: 5a86bb1e96dfce0b63a151420c946f8bfd578ec5 [file] [log] [blame]
Dan Williams6f231dd2011-07-02 22:56:22 -07001/*
2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * BSD LICENSE
25 *
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
38 * distribution.
39 * * Neither the name of Intel Corporation nor the names of its
40 * contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 */
Dave Jiang2d9c2242011-05-04 18:45:05 -070055#include <scsi/sas.h>
Dan Williams6f231dd2011-07-02 22:56:22 -070056#include "isci.h"
Dan Williams6f231dd2011-07-02 22:56:22 -070057#include "port.h"
58#include "remote_device.h"
59#include "request.h"
Dan Williams88f3b622011-04-22 19:18:03 -070060#include "remote_node_context.h"
Dan Williams88f3b622011-04-22 19:18:03 -070061#include "scu_event_codes.h"
Dan Williams6f231dd2011-07-02 22:56:22 -070062#include "task.h"
63
Dan Williamsab2e8f72011-04-27 16:32:45 -070064/**
Dan Williamsab2e8f72011-04-27 16:32:45 -070065 * isci_remote_device_not_ready() - This function is called by the scic when
66 * the remote device is not ready. We mark the isci device as ready (not
67 * "ready_for_io") and signal the waiting proccess.
68 * @isci_host: This parameter specifies the isci host object.
69 * @isci_device: This parameter specifies the remote device
70 *
Jeff Skirvin9274f452011-06-23 17:09:02 -070071 * scic_lock is held on entrance to this function.
Dan Williamsab2e8f72011-04-27 16:32:45 -070072 */
73static void isci_remote_device_not_ready(struct isci_host *ihost,
74 struct isci_remote_device *idev, u32 reason)
75{
Jeff Skirvin9274f452011-06-23 17:09:02 -070076 struct isci_request * ireq;
77
Dan Williamsab2e8f72011-04-27 16:32:45 -070078 dev_dbg(&ihost->pdev->dev,
79 "%s: isci_device = %p\n", __func__, idev);
80
Jeff Skirvin9274f452011-06-23 17:09:02 -070081 switch (reason) {
82 case SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED:
Dan Williams209fae12011-06-13 17:39:44 -070083 set_bit(IDEV_GONE, &idev->flags);
Jeff Skirvin9274f452011-06-23 17:09:02 -070084 break;
85 case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED:
86 set_bit(IDEV_IO_NCQERROR, &idev->flags);
87
88 /* Kill all outstanding requests for the device. */
89 list_for_each_entry(ireq, &idev->reqs_in_process, dev_node) {
90
91 dev_dbg(&ihost->pdev->dev,
92 "%s: isci_device = %p request = %p\n",
93 __func__, idev, ireq);
94
95 scic_controller_terminate_request(&ihost->sci,
96 &idev->sci,
97 &ireq->sci);
98 }
99 /* Fall through into the default case... */
100 default:
Dan Williamsf2088262011-06-16 11:26:12 -0700101 clear_bit(IDEV_IO_READY, &idev->flags);
Jeff Skirvin9274f452011-06-23 17:09:02 -0700102 break;
103 }
Dan Williamsab2e8f72011-04-27 16:32:45 -0700104}
105
106/**
107 * isci_remote_device_ready() - This function is called by the scic when the
108 * remote device is ready. We mark the isci device as ready and signal the
109 * waiting proccess.
110 * @ihost: our valid isci_host
111 * @idev: remote device
112 *
113 */
114static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote_device *idev)
115{
116 dev_dbg(&ihost->pdev->dev,
117 "%s: idev = %p\n", __func__, idev);
118
Jeff Skirvin9274f452011-06-23 17:09:02 -0700119 clear_bit(IDEV_IO_NCQERROR, &idev->flags);
Dan Williamsf2088262011-06-16 11:26:12 -0700120 set_bit(IDEV_IO_READY, &idev->flags);
Dan Williamsab2e8f72011-04-27 16:32:45 -0700121 if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags))
122 wake_up(&ihost->eventq);
123}
124
Dan Williamsec575662011-05-01 14:19:25 -0700125/* called once the remote node context is ready to be freed.
126 * The remote device can now report that its stop operation is complete. none
127 */
128static void rnc_destruct_done(void *_dev)
Dan Williams88f3b622011-04-22 19:18:03 -0700129{
Dan Williamsec575662011-05-01 14:19:25 -0700130 struct scic_sds_remote_device *sci_dev = _dev;
131
132 BUG_ON(sci_dev->started_request_count != 0);
Edmund Nadolskie3013702011-06-02 00:10:43 +0000133 sci_change_state(&sci_dev->sm, SCI_DEV_STOPPED);
Dan Williamsec575662011-05-01 14:19:25 -0700134}
135
136static enum sci_status scic_sds_remote_device_terminate_requests(struct scic_sds_remote_device *sci_dev)
137{
138 struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
Dan Williamsdb056252011-06-17 14:18:39 -0700139 struct isci_host *ihost = scic_to_ihost(scic);
Dan Williamsec575662011-05-01 14:19:25 -0700140 u32 i, request_count = sci_dev->started_request_count;
141 enum sci_status status = SCI_SUCCESS;
142
143 for (i = 0; i < SCI_MAX_IO_REQUESTS && i < request_count; i++) {
Dan Williamsdb056252011-06-17 14:18:39 -0700144 struct isci_request *ireq = ihost->reqs[i];
145 struct scic_sds_request *sci_req = &ireq->sci;
Dan Williamsec575662011-05-01 14:19:25 -0700146 enum sci_status s;
147
Dan Williamsdb056252011-06-17 14:18:39 -0700148 if (!test_bit(IREQ_ACTIVE, &ireq->flags) ||
149 sci_req->target_device != sci_dev)
Dan Williamsec575662011-05-01 14:19:25 -0700150 continue;
Dan Williamsdb056252011-06-17 14:18:39 -0700151
Dan Williamsec575662011-05-01 14:19:25 -0700152 s = scic_controller_terminate_request(scic, sci_dev, sci_req);
153 if (s != SCI_SUCCESS)
154 status = s;
155 }
156
157 return status;
158}
159
160enum sci_status scic_remote_device_stop(struct scic_sds_remote_device *sci_dev,
161 u32 timeout)
162{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000163 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williamsec575662011-05-01 14:19:25 -0700164 enum scic_sds_remote_device_states state = sm->current_state_id;
165
166 switch (state) {
Edmund Nadolskie3013702011-06-02 00:10:43 +0000167 case SCI_DEV_INITIAL:
168 case SCI_DEV_FAILED:
169 case SCI_DEV_FINAL:
Dan Williamsec575662011-05-01 14:19:25 -0700170 default:
171 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
172 __func__, state);
173 return SCI_FAILURE_INVALID_STATE;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000174 case SCI_DEV_STOPPED:
Dan Williamsec575662011-05-01 14:19:25 -0700175 return SCI_SUCCESS;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000176 case SCI_DEV_STARTING:
Dan Williamsec575662011-05-01 14:19:25 -0700177 /* device not started so there had better be no requests */
178 BUG_ON(sci_dev->started_request_count != 0);
179 scic_sds_remote_node_context_destruct(&sci_dev->rnc,
180 rnc_destruct_done, sci_dev);
181 /* Transition to the stopping state and wait for the
182 * remote node to complete being posted and invalidated.
183 */
Edmund Nadolskie3013702011-06-02 00:10:43 +0000184 sci_change_state(sm, SCI_DEV_STOPPING);
Dan Williamsec575662011-05-01 14:19:25 -0700185 return SCI_SUCCESS;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000186 case SCI_DEV_READY:
187 case SCI_STP_DEV_IDLE:
188 case SCI_STP_DEV_CMD:
189 case SCI_STP_DEV_NCQ:
190 case SCI_STP_DEV_NCQ_ERROR:
191 case SCI_STP_DEV_AWAIT_RESET:
192 case SCI_SMP_DEV_IDLE:
193 case SCI_SMP_DEV_CMD:
194 sci_change_state(sm, SCI_DEV_STOPPING);
Dan Williamsec575662011-05-01 14:19:25 -0700195 if (sci_dev->started_request_count == 0) {
196 scic_sds_remote_node_context_destruct(&sci_dev->rnc,
197 rnc_destruct_done, sci_dev);
198 return SCI_SUCCESS;
199 } else
200 return scic_sds_remote_device_terminate_requests(sci_dev);
201 break;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000202 case SCI_DEV_STOPPING:
Dan Williamsec575662011-05-01 14:19:25 -0700203 /* All requests should have been terminated, but if there is an
204 * attempt to stop a device already in the stopping state, then
205 * try again to terminate.
206 */
207 return scic_sds_remote_device_terminate_requests(sci_dev);
Edmund Nadolskie3013702011-06-02 00:10:43 +0000208 case SCI_DEV_RESETTING:
209 sci_change_state(sm, SCI_DEV_STOPPING);
Dan Williamsec575662011-05-01 14:19:25 -0700210 return SCI_SUCCESS;
211 }
Dan Williams88f3b622011-04-22 19:18:03 -0700212}
Dan Williams6f231dd2011-07-02 22:56:22 -0700213
Dan Williams4fd0d2e2011-05-01 14:48:54 -0700214enum sci_status scic_remote_device_reset(struct scic_sds_remote_device *sci_dev)
Dan Williams88f3b622011-04-22 19:18:03 -0700215{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000216 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williams4fd0d2e2011-05-01 14:48:54 -0700217 enum scic_sds_remote_device_states state = sm->current_state_id;
218
219 switch (state) {
Edmund Nadolskie3013702011-06-02 00:10:43 +0000220 case SCI_DEV_INITIAL:
221 case SCI_DEV_STOPPED:
222 case SCI_DEV_STARTING:
223 case SCI_SMP_DEV_IDLE:
224 case SCI_SMP_DEV_CMD:
225 case SCI_DEV_STOPPING:
226 case SCI_DEV_FAILED:
227 case SCI_DEV_RESETTING:
228 case SCI_DEV_FINAL:
Dan Williams4fd0d2e2011-05-01 14:48:54 -0700229 default:
230 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
231 __func__, state);
232 return SCI_FAILURE_INVALID_STATE;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000233 case SCI_DEV_READY:
234 case SCI_STP_DEV_IDLE:
235 case SCI_STP_DEV_CMD:
236 case SCI_STP_DEV_NCQ:
237 case SCI_STP_DEV_NCQ_ERROR:
238 case SCI_STP_DEV_AWAIT_RESET:
239 sci_change_state(sm, SCI_DEV_RESETTING);
Dan Williams4fd0d2e2011-05-01 14:48:54 -0700240 return SCI_SUCCESS;
241 }
Dan Williams88f3b622011-04-22 19:18:03 -0700242}
243
Dan Williams81515182011-05-01 14:53:00 -0700244enum sci_status scic_remote_device_reset_complete(struct scic_sds_remote_device *sci_dev)
Dan Williams88f3b622011-04-22 19:18:03 -0700245{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000246 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williams81515182011-05-01 14:53:00 -0700247 enum scic_sds_remote_device_states state = sm->current_state_id;
Dan Williams88f3b622011-04-22 19:18:03 -0700248
Edmund Nadolskie3013702011-06-02 00:10:43 +0000249 if (state != SCI_DEV_RESETTING) {
Dan Williams81515182011-05-01 14:53:00 -0700250 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
251 __func__, state);
252 return SCI_FAILURE_INVALID_STATE;
253 }
254
Edmund Nadolskie3013702011-06-02 00:10:43 +0000255 sci_change_state(sm, SCI_DEV_READY);
Dan Williams81515182011-05-01 14:53:00 -0700256 return SCI_SUCCESS;
257}
Dan Williams88f3b622011-04-22 19:18:03 -0700258
Dan Williams323f0ec2011-05-01 16:15:47 -0700259enum sci_status scic_sds_remote_device_suspend(struct scic_sds_remote_device *sci_dev,
260 u32 suspend_type)
Dan Williams88f3b622011-04-22 19:18:03 -0700261{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000262 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williams323f0ec2011-05-01 16:15:47 -0700263 enum scic_sds_remote_device_states state = sm->current_state_id;
264
Edmund Nadolskie3013702011-06-02 00:10:43 +0000265 if (state != SCI_STP_DEV_CMD) {
Dan Williams323f0ec2011-05-01 16:15:47 -0700266 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
267 __func__, state);
268 return SCI_FAILURE_INVALID_STATE;
269 }
270
271 return scic_sds_remote_node_context_suspend(&sci_dev->rnc,
272 suspend_type, NULL, NULL);
Dan Williams88f3b622011-04-22 19:18:03 -0700273}
274
Dan Williams01bec772011-05-01 16:51:11 -0700275enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_device *sci_dev,
276 u32 frame_index)
Dan Williams88f3b622011-04-22 19:18:03 -0700277{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000278 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williams01bec772011-05-01 16:51:11 -0700279 enum scic_sds_remote_device_states state = sm->current_state_id;
280 struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
281 enum sci_status status;
282
283 switch (state) {
Edmund Nadolskie3013702011-06-02 00:10:43 +0000284 case SCI_DEV_INITIAL:
285 case SCI_DEV_STOPPED:
286 case SCI_DEV_STARTING:
287 case SCI_STP_DEV_IDLE:
288 case SCI_SMP_DEV_IDLE:
289 case SCI_DEV_FINAL:
Dan Williams01bec772011-05-01 16:51:11 -0700290 default:
291 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
292 __func__, state);
293 /* Return the frame back to the controller */
294 scic_sds_controller_release_frame(scic, frame_index);
295 return SCI_FAILURE_INVALID_STATE;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000296 case SCI_DEV_READY:
297 case SCI_STP_DEV_NCQ_ERROR:
298 case SCI_STP_DEV_AWAIT_RESET:
299 case SCI_DEV_STOPPING:
300 case SCI_DEV_FAILED:
301 case SCI_DEV_RESETTING: {
Dan Williams01bec772011-05-01 16:51:11 -0700302 struct scic_sds_request *sci_req;
Dave Jiang2d9c2242011-05-04 18:45:05 -0700303 struct ssp_frame_hdr hdr;
304 void *frame_header;
305 ssize_t word_cnt;
Dan Williams01bec772011-05-01 16:51:11 -0700306
307 status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
308 frame_index,
Dave Jiang2d9c2242011-05-04 18:45:05 -0700309 &frame_header);
Dan Williams01bec772011-05-01 16:51:11 -0700310 if (status != SCI_SUCCESS)
311 return status;
312
Dave Jiang2d9c2242011-05-04 18:45:05 -0700313 word_cnt = sizeof(hdr) / sizeof(u32);
314 sci_swab32_cpy(&hdr, frame_header, word_cnt);
315
316 sci_req = scic_request_by_tag(scic, be16_to_cpu(hdr.tag));
Dan Williams01bec772011-05-01 16:51:11 -0700317 if (sci_req && sci_req->target_device == sci_dev) {
318 /* The IO request is now in charge of releasing the frame */
Dan Williamsd1c637c32011-05-11 08:27:47 -0700319 status = scic_sds_io_request_frame_handler(sci_req, frame_index);
Dan Williams01bec772011-05-01 16:51:11 -0700320 } else {
321 /* We could not map this tag to a valid IO
322 * request Just toss the frame and continue
323 */
324 scic_sds_controller_release_frame(scic, frame_index);
325 }
326 break;
327 }
Edmund Nadolskie3013702011-06-02 00:10:43 +0000328 case SCI_STP_DEV_NCQ: {
Dave Jiange76d6182011-05-04 15:02:03 -0700329 struct dev_to_host_fis *hdr;
Dan Williams01bec772011-05-01 16:51:11 -0700330
331 status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
332 frame_index,
333 (void **)&hdr);
334 if (status != SCI_SUCCESS)
335 return status;
336
Dave Jiange76d6182011-05-04 15:02:03 -0700337 if (hdr->fis_type == FIS_SETDEVBITS &&
338 (hdr->status & ATA_ERR)) {
Dan Williams01bec772011-05-01 16:51:11 -0700339 sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
340
341 /* TODO Check sactive and complete associated IO if any. */
Edmund Nadolskie3013702011-06-02 00:10:43 +0000342 sci_change_state(sm, SCI_STP_DEV_NCQ_ERROR);
Dave Jiange76d6182011-05-04 15:02:03 -0700343 } else if (hdr->fis_type == FIS_REGD2H &&
344 (hdr->status & ATA_ERR)) {
Dan Williams01bec772011-05-01 16:51:11 -0700345 /*
346 * Some devices return D2H FIS when an NCQ error is detected.
347 * Treat this like an SDB error FIS ready reason.
348 */
349 sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000350 sci_change_state(&sci_dev->sm, SCI_STP_DEV_NCQ_ERROR);
Dan Williams01bec772011-05-01 16:51:11 -0700351 } else
352 status = SCI_FAILURE;
353
354 scic_sds_controller_release_frame(scic, frame_index);
355 break;
356 }
Edmund Nadolskie3013702011-06-02 00:10:43 +0000357 case SCI_STP_DEV_CMD:
358 case SCI_SMP_DEV_CMD:
Dan Williams01bec772011-05-01 16:51:11 -0700359 /* The device does not process any UF received from the hardware while
360 * in this state. All unsolicited frames are forwarded to the io request
361 * object.
362 */
363 status = scic_sds_io_request_frame_handler(sci_dev->working_request, frame_index);
364 break;
365 }
366
367 return status;
Dan Williams88f3b622011-04-22 19:18:03 -0700368}
369
Dan Williamse6225712011-05-01 16:26:09 -0700370static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev)
Dan Williams88f3b622011-04-22 19:18:03 -0700371{
Dan Williamse6225712011-05-01 16:26:09 -0700372
Edmund Nadolskie3013702011-06-02 00:10:43 +0000373 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williamse6225712011-05-01 16:26:09 -0700374 enum scic_sds_remote_device_states state = sm->current_state_id;
375
376 switch (state) {
Edmund Nadolskie3013702011-06-02 00:10:43 +0000377 case SCI_DEV_READY:
378 case SCI_STP_DEV_IDLE:
379 case SCI_STP_DEV_CMD:
380 case SCI_STP_DEV_NCQ:
381 case SCI_STP_DEV_NCQ_ERROR:
382 case SCI_STP_DEV_AWAIT_RESET:
383 case SCI_SMP_DEV_IDLE:
384 case SCI_SMP_DEV_CMD:
Dan Williamse6225712011-05-01 16:26:09 -0700385 return true;
386 default:
387 return false;
388 }
389}
390
391enum sci_status scic_sds_remote_device_event_handler(struct scic_sds_remote_device *sci_dev,
392 u32 event_code)
393{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000394 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williamse6225712011-05-01 16:26:09 -0700395 enum scic_sds_remote_device_states state = sm->current_state_id;
396 enum sci_status status;
397
398 switch (scu_get_event_type(event_code)) {
399 case SCU_EVENT_TYPE_RNC_OPS_MISC:
400 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
401 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
402 status = scic_sds_remote_node_context_event_handler(&sci_dev->rnc, event_code);
403 break;
404 case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
405 if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) {
406 status = SCI_SUCCESS;
407
408 /* Suspend the associated RNC */
409 scic_sds_remote_node_context_suspend(&sci_dev->rnc,
410 SCI_SOFTWARE_SUSPENSION,
411 NULL, NULL);
412
413 dev_dbg(scirdev_to_dev(sci_dev),
414 "%s: device: %p event code: %x: %s\n",
415 __func__, sci_dev, event_code,
416 is_remote_device_ready(sci_dev)
417 ? "I_T_Nexus_Timeout event"
418 : "I_T_Nexus_Timeout event in wrong state");
419
420 break;
421 }
422 /* Else, fall through and treat as unhandled... */
423 default:
424 dev_dbg(scirdev_to_dev(sci_dev),
425 "%s: device: %p event code: %x: %s\n",
426 __func__, sci_dev, event_code,
427 is_remote_device_ready(sci_dev)
428 ? "unexpected event"
429 : "unexpected event in wrong state");
430 status = SCI_FAILURE_INVALID_STATE;
431 break;
432 }
433
434 if (status != SCI_SUCCESS)
435 return status;
436
Edmund Nadolskie3013702011-06-02 00:10:43 +0000437 if (state == SCI_STP_DEV_IDLE) {
Dan Williamse6225712011-05-01 16:26:09 -0700438
439 /* We pick up suspension events to handle specifically to this
440 * state. We resume the RNC right away.
441 */
442 if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
443 scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX)
444 status = scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL);
445 }
446
447 return status;
Dan Williams88f3b622011-04-22 19:18:03 -0700448}
449
Dan Williams18606552011-05-01 14:57:11 -0700450static void scic_sds_remote_device_start_request(struct scic_sds_remote_device *sci_dev,
451 struct scic_sds_request *sci_req,
452 enum sci_status status)
Dan Williams88f3b622011-04-22 19:18:03 -0700453{
Dan Williams18606552011-05-01 14:57:11 -0700454 struct scic_sds_port *sci_port = sci_dev->owning_port;
455
456 /* cleanup requests that failed after starting on the port */
457 if (status != SCI_SUCCESS)
458 scic_sds_port_complete_io(sci_port, sci_dev, sci_req);
Dan Williams209fae12011-06-13 17:39:44 -0700459 else {
460 kref_get(&sci_dev_to_idev(sci_dev)->kref);
Dan Williams18606552011-05-01 14:57:11 -0700461 scic_sds_remote_device_increment_request_count(sci_dev);
Dan Williams209fae12011-06-13 17:39:44 -0700462 }
Dan Williams18606552011-05-01 14:57:11 -0700463}
464
465enum sci_status scic_sds_remote_device_start_io(struct scic_sds_controller *scic,
466 struct scic_sds_remote_device *sci_dev,
467 struct scic_sds_request *sci_req)
468{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000469 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williams18606552011-05-01 14:57:11 -0700470 enum scic_sds_remote_device_states state = sm->current_state_id;
471 struct scic_sds_port *sci_port = sci_dev->owning_port;
Dan Williams67ea8382011-05-08 11:47:15 -0700472 struct isci_request *ireq = sci_req_to_ireq(sci_req);
Dan Williams18606552011-05-01 14:57:11 -0700473 enum sci_status status;
474
475 switch (state) {
Edmund Nadolskie3013702011-06-02 00:10:43 +0000476 case SCI_DEV_INITIAL:
477 case SCI_DEV_STOPPED:
478 case SCI_DEV_STARTING:
479 case SCI_STP_DEV_NCQ_ERROR:
480 case SCI_DEV_STOPPING:
481 case SCI_DEV_FAILED:
482 case SCI_DEV_RESETTING:
483 case SCI_DEV_FINAL:
Dan Williams18606552011-05-01 14:57:11 -0700484 default:
485 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
486 __func__, state);
487 return SCI_FAILURE_INVALID_STATE;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000488 case SCI_DEV_READY:
Dan Williams18606552011-05-01 14:57:11 -0700489 /* attempt to start an io request for this device object. The remote
490 * device object will issue the start request for the io and if
491 * successful it will start the request for the port object then
492 * increment its own request count.
493 */
494 status = scic_sds_port_start_io(sci_port, sci_dev, sci_req);
495 if (status != SCI_SUCCESS)
496 return status;
497
498 status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req);
499 if (status != SCI_SUCCESS)
500 break;
501
502 status = scic_sds_request_start(sci_req);
503 break;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000504 case SCI_STP_DEV_IDLE: {
Dan Williams18606552011-05-01 14:57:11 -0700505 /* handle the start io operation for a sata device that is in
506 * the command idle state. - Evalute the type of IO request to
507 * be started - If its an NCQ request change to NCQ substate -
508 * If its any other command change to the CMD substate
509 *
510 * If this is a softreset we may want to have a different
511 * substate.
512 */
513 enum scic_sds_remote_device_states new_state;
Dave Jiange76d6182011-05-04 15:02:03 -0700514 struct sas_task *task = isci_request_access_task(ireq);
Dan Williams18606552011-05-01 14:57:11 -0700515
516 status = scic_sds_port_start_io(sci_port, sci_dev, sci_req);
517 if (status != SCI_SUCCESS)
518 return status;
519
520 status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req);
521 if (status != SCI_SUCCESS)
522 break;
523
Piotr Sawickif4636a72011-05-10 23:50:32 +0000524 status = scic_sds_request_start(sci_req);
Dan Williams18606552011-05-01 14:57:11 -0700525 if (status != SCI_SUCCESS)
526 break;
527
Dave Jiange76d6182011-05-04 15:02:03 -0700528 if (task->ata_task.use_ncq)
Edmund Nadolskie3013702011-06-02 00:10:43 +0000529 new_state = SCI_STP_DEV_NCQ;
Dan Williams18606552011-05-01 14:57:11 -0700530 else {
531 sci_dev->working_request = sci_req;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000532 new_state = SCI_STP_DEV_CMD;
Dan Williams18606552011-05-01 14:57:11 -0700533 }
Edmund Nadolskie3013702011-06-02 00:10:43 +0000534 sci_change_state(sm, new_state);
Dan Williams18606552011-05-01 14:57:11 -0700535 break;
536 }
Edmund Nadolskie3013702011-06-02 00:10:43 +0000537 case SCI_STP_DEV_NCQ: {
Dave Jiange76d6182011-05-04 15:02:03 -0700538 struct sas_task *task = isci_request_access_task(ireq);
539
540 if (task->ata_task.use_ncq) {
Dan Williams18606552011-05-01 14:57:11 -0700541 status = scic_sds_port_start_io(sci_port, sci_dev, sci_req);
542 if (status != SCI_SUCCESS)
543 return status;
544
545 status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req);
546 if (status != SCI_SUCCESS)
547 break;
548
Piotr Sawickif4636a72011-05-10 23:50:32 +0000549 status = scic_sds_request_start(sci_req);
Dan Williams18606552011-05-01 14:57:11 -0700550 } else
551 return SCI_FAILURE_INVALID_STATE;
552 break;
Dave Jiange76d6182011-05-04 15:02:03 -0700553 }
Edmund Nadolskie3013702011-06-02 00:10:43 +0000554 case SCI_STP_DEV_AWAIT_RESET:
Dan Williams18606552011-05-01 14:57:11 -0700555 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000556 case SCI_SMP_DEV_IDLE:
Dan Williams18606552011-05-01 14:57:11 -0700557 status = scic_sds_port_start_io(sci_port, sci_dev, sci_req);
558 if (status != SCI_SUCCESS)
559 return status;
560
561 status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, sci_req);
562 if (status != SCI_SUCCESS)
563 break;
564
565 status = scic_sds_request_start(sci_req);
566 if (status != SCI_SUCCESS)
567 break;
568
569 sci_dev->working_request = sci_req;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000570 sci_change_state(&sci_dev->sm, SCI_SMP_DEV_CMD);
Dan Williams18606552011-05-01 14:57:11 -0700571 break;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000572 case SCI_STP_DEV_CMD:
573 case SCI_SMP_DEV_CMD:
Dan Williams18606552011-05-01 14:57:11 -0700574 /* device is already handling a command it can not accept new commands
575 * until this one is complete.
576 */
577 return SCI_FAILURE_INVALID_STATE;
578 }
579
580 scic_sds_remote_device_start_request(sci_dev, sci_req, status);
581 return status;
Dan Williams88f3b622011-04-22 19:18:03 -0700582}
583
Dan Williams10a09e62011-05-01 15:33:43 -0700584static enum sci_status common_complete_io(struct scic_sds_port *sci_port,
585 struct scic_sds_remote_device *sci_dev,
586 struct scic_sds_request *sci_req)
Dan Williams88f3b622011-04-22 19:18:03 -0700587{
Dan Williams10a09e62011-05-01 15:33:43 -0700588 enum sci_status status;
589
590 status = scic_sds_request_complete(sci_req);
591 if (status != SCI_SUCCESS)
592 return status;
593
594 status = scic_sds_port_complete_io(sci_port, sci_dev, sci_req);
595 if (status != SCI_SUCCESS)
596 return status;
597
598 scic_sds_remote_device_decrement_request_count(sci_dev);
599 return status;
600}
601
602enum sci_status scic_sds_remote_device_complete_io(struct scic_sds_controller *scic,
603 struct scic_sds_remote_device *sci_dev,
604 struct scic_sds_request *sci_req)
605{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000606 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williams10a09e62011-05-01 15:33:43 -0700607 enum scic_sds_remote_device_states state = sm->current_state_id;
608 struct scic_sds_port *sci_port = sci_dev->owning_port;
609 enum sci_status status;
610
611 switch (state) {
Edmund Nadolskie3013702011-06-02 00:10:43 +0000612 case SCI_DEV_INITIAL:
613 case SCI_DEV_STOPPED:
614 case SCI_DEV_STARTING:
615 case SCI_STP_DEV_IDLE:
616 case SCI_SMP_DEV_IDLE:
617 case SCI_DEV_FAILED:
618 case SCI_DEV_FINAL:
Dan Williams10a09e62011-05-01 15:33:43 -0700619 default:
620 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
621 __func__, state);
622 return SCI_FAILURE_INVALID_STATE;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000623 case SCI_DEV_READY:
624 case SCI_STP_DEV_AWAIT_RESET:
625 case SCI_DEV_RESETTING:
Dan Williams10a09e62011-05-01 15:33:43 -0700626 status = common_complete_io(sci_port, sci_dev, sci_req);
627 break;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000628 case SCI_STP_DEV_CMD:
629 case SCI_STP_DEV_NCQ:
630 case SCI_STP_DEV_NCQ_ERROR:
Dan Williams10a09e62011-05-01 15:33:43 -0700631 status = common_complete_io(sci_port, sci_dev, sci_req);
632 if (status != SCI_SUCCESS)
633 break;
634
635 if (sci_req->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) {
636 /* This request causes hardware error, device needs to be Lun Reset.
637 * So here we force the state machine to IDLE state so the rest IOs
638 * can reach RNC state handler, these IOs will be completed by RNC with
639 * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE".
640 */
Edmund Nadolskie3013702011-06-02 00:10:43 +0000641 sci_change_state(sm, SCI_STP_DEV_AWAIT_RESET);
Dan Williams10a09e62011-05-01 15:33:43 -0700642 } else if (scic_sds_remote_device_get_request_count(sci_dev) == 0)
Edmund Nadolskie3013702011-06-02 00:10:43 +0000643 sci_change_state(sm, SCI_STP_DEV_IDLE);
Dan Williams10a09e62011-05-01 15:33:43 -0700644 break;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000645 case SCI_SMP_DEV_CMD:
Dan Williams10a09e62011-05-01 15:33:43 -0700646 status = common_complete_io(sci_port, sci_dev, sci_req);
647 if (status != SCI_SUCCESS)
648 break;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000649 sci_change_state(sm, SCI_SMP_DEV_IDLE);
Dan Williams10a09e62011-05-01 15:33:43 -0700650 break;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000651 case SCI_DEV_STOPPING:
Dan Williams10a09e62011-05-01 15:33:43 -0700652 status = common_complete_io(sci_port, sci_dev, sci_req);
653 if (status != SCI_SUCCESS)
654 break;
655
656 if (scic_sds_remote_device_get_request_count(sci_dev) == 0)
657 scic_sds_remote_node_context_destruct(&sci_dev->rnc,
658 rnc_destruct_done,
659 sci_dev);
660 break;
661 }
662
663 if (status != SCI_SUCCESS)
664 dev_err(scirdev_to_dev(sci_dev),
665 "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
666 "could not complete\n", __func__, sci_port,
667 sci_dev, sci_req, status);
Dan Williams209fae12011-06-13 17:39:44 -0700668 else
669 isci_put_device(sci_dev_to_idev(sci_dev));
Dan Williams10a09e62011-05-01 15:33:43 -0700670
671 return status;
Dan Williams88f3b622011-04-22 19:18:03 -0700672}
673
Dan Williams84b9b022011-05-01 15:53:25 -0700674static void scic_sds_remote_device_continue_request(void *dev)
Dan Williams88f3b622011-04-22 19:18:03 -0700675{
Dan Williams84b9b022011-05-01 15:53:25 -0700676 struct scic_sds_remote_device *sci_dev = dev;
677
678 /* we need to check if this request is still valid to continue. */
679 if (sci_dev->working_request)
680 scic_controller_continue_io(sci_dev->working_request);
681}
682
683enum sci_status scic_sds_remote_device_start_task(struct scic_sds_controller *scic,
684 struct scic_sds_remote_device *sci_dev,
685 struct scic_sds_request *sci_req)
686{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000687 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williams84b9b022011-05-01 15:53:25 -0700688 enum scic_sds_remote_device_states state = sm->current_state_id;
689 struct scic_sds_port *sci_port = sci_dev->owning_port;
690 enum sci_status status;
691
692 switch (state) {
Edmund Nadolskie3013702011-06-02 00:10:43 +0000693 case SCI_DEV_INITIAL:
694 case SCI_DEV_STOPPED:
695 case SCI_DEV_STARTING:
696 case SCI_SMP_DEV_IDLE:
697 case SCI_SMP_DEV_CMD:
698 case SCI_DEV_STOPPING:
699 case SCI_DEV_FAILED:
700 case SCI_DEV_RESETTING:
701 case SCI_DEV_FINAL:
Dan Williams84b9b022011-05-01 15:53:25 -0700702 default:
703 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
704 __func__, state);
705 return SCI_FAILURE_INVALID_STATE;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000706 case SCI_STP_DEV_IDLE:
707 case SCI_STP_DEV_CMD:
708 case SCI_STP_DEV_NCQ:
709 case SCI_STP_DEV_NCQ_ERROR:
710 case SCI_STP_DEV_AWAIT_RESET:
Dan Williams84b9b022011-05-01 15:53:25 -0700711 status = scic_sds_port_start_io(sci_port, sci_dev, sci_req);
712 if (status != SCI_SUCCESS)
713 return status;
714
715 status = scic_sds_remote_node_context_start_task(&sci_dev->rnc, sci_req);
716 if (status != SCI_SUCCESS)
717 goto out;
718
Piotr Sawickif4636a72011-05-10 23:50:32 +0000719 status = scic_sds_request_start(sci_req);
Dan Williams84b9b022011-05-01 15:53:25 -0700720 if (status != SCI_SUCCESS)
721 goto out;
722
723 /* Note: If the remote device state is not IDLE this will
724 * replace the request that probably resulted in the task
725 * management request.
726 */
727 sci_dev->working_request = sci_req;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000728 sci_change_state(sm, SCI_STP_DEV_CMD);
Dan Williams84b9b022011-05-01 15:53:25 -0700729
730 /* The remote node context must cleanup the TCi to NCQ mapping
731 * table. The only way to do this correctly is to either write
732 * to the TLCR register or to invalidate and repost the RNC. In
733 * either case the remote node context state machine will take
734 * the correct action when the remote node context is suspended
735 * and later resumed.
736 */
737 scic_sds_remote_node_context_suspend(&sci_dev->rnc,
738 SCI_SOFTWARE_SUSPENSION, NULL, NULL);
739 scic_sds_remote_node_context_resume(&sci_dev->rnc,
740 scic_sds_remote_device_continue_request,
741 sci_dev);
742
743 out:
744 scic_sds_remote_device_start_request(sci_dev, sci_req, status);
745 /* We need to let the controller start request handler know that
746 * it can't post TC yet. We will provide a callback function to
747 * post TC when RNC gets resumed.
748 */
749 return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000750 case SCI_DEV_READY:
Dan Williams84b9b022011-05-01 15:53:25 -0700751 status = scic_sds_port_start_io(sci_port, sci_dev, sci_req);
752 if (status != SCI_SUCCESS)
753 return status;
754
755 status = scic_sds_remote_node_context_start_task(&sci_dev->rnc, sci_req);
756 if (status != SCI_SUCCESS)
757 break;
758
759 status = scic_sds_request_start(sci_req);
760 break;
761 }
762 scic_sds_remote_device_start_request(sci_dev, sci_req, status);
763
764 return status;
Dan Williams88f3b622011-04-22 19:18:03 -0700765}
766
767/**
768 *
Dan Williams88f3b622011-04-22 19:18:03 -0700769 * @sci_dev:
770 * @request:
771 *
772 * This method takes the request and bulids an appropriate SCU context for the
773 * request and then requests the controller to post the request. none
774 */
775void scic_sds_remote_device_post_request(
776 struct scic_sds_remote_device *sci_dev,
777 u32 request)
778{
779 u32 context;
780
781 context = scic_sds_remote_device_build_command_context(sci_dev, request);
782
783 scic_sds_controller_post_request(
784 scic_sds_remote_device_get_controller(sci_dev),
785 context
786 );
787}
788
Dan Williamsab2e8f72011-04-27 16:32:45 -0700789/* called once the remote node context has transisitioned to a
Dan Williams88f3b622011-04-22 19:18:03 -0700790 * ready state. This is the indication that the remote device object can also
Dan Williamsab2e8f72011-04-27 16:32:45 -0700791 * transition to ready.
Dan Williams88f3b622011-04-22 19:18:03 -0700792 */
Dan Williamseb229672011-05-01 14:05:57 -0700793static void remote_device_resume_done(void *_dev)
Dan Williams88f3b622011-04-22 19:18:03 -0700794{
Dan Williamsab2e8f72011-04-27 16:32:45 -0700795 struct scic_sds_remote_device *sci_dev = _dev;
Dan Williams88f3b622011-04-22 19:18:03 -0700796
Dan Williamse6225712011-05-01 16:26:09 -0700797 if (is_remote_device_ready(sci_dev))
798 return;
Dan Williams88f3b622011-04-22 19:18:03 -0700799
Dan Williamse6225712011-05-01 16:26:09 -0700800 /* go 'ready' if we are not already in a ready state */
Edmund Nadolskie3013702011-06-02 00:10:43 +0000801 sci_change_state(&sci_dev->sm, SCI_DEV_READY);
Dan Williams88f3b622011-04-22 19:18:03 -0700802}
803
Dan Williamsab2e8f72011-04-27 16:32:45 -0700804static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev)
805{
806 struct scic_sds_remote_device *sci_dev = _dev;
807 struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
808 struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
809
810 /* For NCQ operation we do not issue a isci_remote_device_not_ready().
811 * As a result, avoid sending the ready notification.
812 */
Edmund Nadolskie3013702011-06-02 00:10:43 +0000813 if (sci_dev->sm.previous_state_id != SCI_STP_DEV_NCQ)
Artur Wojcikcc3dbd02011-05-04 07:58:16 +0000814 isci_remote_device_ready(scic_to_ihost(scic), idev);
Dan Williamsab2e8f72011-04-27 16:32:45 -0700815}
816
Dan Williams9269e0e2011-05-12 07:42:17 -0700817static void scic_sds_remote_device_initial_state_enter(struct sci_base_state_machine *sm)
Dan Williams88f3b622011-04-22 19:18:03 -0700818{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000819 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williams88f3b622011-04-22 19:18:03 -0700820
Dan Williams88f3b622011-04-22 19:18:03 -0700821 /* Initial state is a transitional state to the stopped state */
Edmund Nadolskie3013702011-06-02 00:10:43 +0000822 sci_change_state(&sci_dev->sm, SCI_DEV_STOPPED);
Dan Williams88f3b622011-04-22 19:18:03 -0700823}
824
825/**
Dan Williams88f3b622011-04-22 19:18:03 -0700826 * scic_remote_device_destruct() - free remote node context and destruct
827 * @remote_device: This parameter specifies the remote device to be destructed.
828 *
829 * Remote device objects are a limited resource. As such, they must be
830 * protected. Thus calls to construct and destruct are mutually exclusive and
831 * non-reentrant. The return value shall indicate if the device was
832 * successfully destructed or if some failure occurred. enum sci_status This value
833 * is returned if the device is successfully destructed.
834 * SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the supplied
835 * device isn't valid (e.g. it's already been destoryed, the handle isn't
836 * valid, etc.).
837 */
838static enum sci_status scic_remote_device_destruct(struct scic_sds_remote_device *sci_dev)
839{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000840 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williamsb8d82f62011-05-01 14:38:26 -0700841 enum scic_sds_remote_device_states state = sm->current_state_id;
842 struct scic_sds_controller *scic;
843
Edmund Nadolskie3013702011-06-02 00:10:43 +0000844 if (state != SCI_DEV_STOPPED) {
Dan Williamsb8d82f62011-05-01 14:38:26 -0700845 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
846 __func__, state);
847 return SCI_FAILURE_INVALID_STATE;
848 }
849
850 scic = sci_dev->owning_port->owning_controller;
851 scic_sds_controller_free_remote_node_context(scic, sci_dev,
852 sci_dev->rnc.remote_node_index);
853 sci_dev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
Edmund Nadolskie3013702011-06-02 00:10:43 +0000854 sci_change_state(sm, SCI_DEV_FINAL);
Dan Williamsb8d82f62011-05-01 14:38:26 -0700855
856 return SCI_SUCCESS;
Dan Williams88f3b622011-04-22 19:18:03 -0700857}
858
Dan Williams6f231dd2011-07-02 22:56:22 -0700859/**
860 * isci_remote_device_deconstruct() - This function frees an isci_remote_device.
Dan Williamsd9c37392011-03-03 17:59:32 -0800861 * @ihost: This parameter specifies the isci host object.
862 * @idev: This parameter specifies the remote device to be freed.
Dan Williams6f231dd2011-07-02 22:56:22 -0700863 *
864 */
Dan Williamsd9c37392011-03-03 17:59:32 -0800865static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_remote_device *idev)
Dan Williams6f231dd2011-07-02 22:56:22 -0700866{
Dan Williamsd9c37392011-03-03 17:59:32 -0800867 dev_dbg(&ihost->pdev->dev,
868 "%s: isci_device = %p\n", __func__, idev);
Dan Williams6f231dd2011-07-02 22:56:22 -0700869
870 /* There should not be any outstanding io's. All paths to
871 * here should go through isci_remote_device_nuke_requests.
872 * If we hit this condition, we will need a way to complete
873 * io requests in process */
Dan Williams209fae12011-06-13 17:39:44 -0700874 BUG_ON(!list_empty(&idev->reqs_in_process));
Dan Williams6f231dd2011-07-02 22:56:22 -0700875
Dan Williams57f20f42011-04-21 18:14:45 -0700876 scic_remote_device_destruct(&idev->sci);
Dan Williamsd9c37392011-03-03 17:59:32 -0800877 list_del_init(&idev->node);
Dan Williams209fae12011-06-13 17:39:44 -0700878 isci_put_device(idev);
Dan Williams6f231dd2011-07-02 22:56:22 -0700879}
880
Dan Williams9269e0e2011-05-12 07:42:17 -0700881static void scic_sds_remote_device_stopped_state_enter(struct sci_base_state_machine *sm)
Dan Williams88f3b622011-04-22 19:18:03 -0700882{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000883 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Artur Wojcikcc3dbd02011-05-04 07:58:16 +0000884 struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
885 struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
Dan Williams88f3b622011-04-22 19:18:03 -0700886 u32 prev_state;
887
Dan Williams88f3b622011-04-22 19:18:03 -0700888 /* If we are entering from the stopping state let the SCI User know that
889 * the stop operation has completed.
890 */
Edmund Nadolskie3013702011-06-02 00:10:43 +0000891 prev_state = sci_dev->sm.previous_state_id;
892 if (prev_state == SCI_DEV_STOPPING)
Dan Williamsf2088262011-06-16 11:26:12 -0700893 isci_remote_device_deconstruct(scic_to_ihost(scic), idev);
Dan Williams88f3b622011-04-22 19:18:03 -0700894
895 scic_sds_controller_remote_device_stopped(scic, sci_dev);
896}
897
Dan Williams9269e0e2011-05-12 07:42:17 -0700898static void scic_sds_remote_device_starting_state_enter(struct sci_base_state_machine *sm)
Dan Williams88f3b622011-04-22 19:18:03 -0700899{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000900 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williams88f3b622011-04-22 19:18:03 -0700901 struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
Artur Wojcikcc3dbd02011-05-04 07:58:16 +0000902 struct isci_host *ihost = scic_to_ihost(scic);
Maciej Patelczyk5d937e92011-04-28 22:06:21 +0000903 struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
Dan Williams88f3b622011-04-22 19:18:03 -0700904
Dan Williams88f3b622011-04-22 19:18:03 -0700905 isci_remote_device_not_ready(ihost, idev,
906 SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED);
907}
908
Dan Williams9269e0e2011-05-12 07:42:17 -0700909static void scic_sds_remote_device_ready_state_enter(struct sci_base_state_machine *sm)
Dan Williams88f3b622011-04-22 19:18:03 -0700910{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000911 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williamsab2e8f72011-04-27 16:32:45 -0700912 struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
Artur Wojcikcc3dbd02011-05-04 07:58:16 +0000913 struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
914 struct domain_device *dev = idev->domain_dev;
Dan Williams88f3b622011-04-22 19:18:03 -0700915
Dan Williamsab2e8f72011-04-27 16:32:45 -0700916 if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) {
Edmund Nadolskie3013702011-06-02 00:10:43 +0000917 sci_change_state(&sci_dev->sm, SCI_STP_DEV_IDLE);
Dan Williamsab2e8f72011-04-27 16:32:45 -0700918 } else if (dev_is_expander(dev)) {
Edmund Nadolskie3013702011-06-02 00:10:43 +0000919 sci_change_state(&sci_dev->sm, SCI_SMP_DEV_IDLE);
Dan Williamsab2e8f72011-04-27 16:32:45 -0700920 } else
Artur Wojcikcc3dbd02011-05-04 07:58:16 +0000921 isci_remote_device_ready(scic_to_ihost(scic), idev);
Dan Williams88f3b622011-04-22 19:18:03 -0700922}
923
Dan Williams9269e0e2011-05-12 07:42:17 -0700924static void scic_sds_remote_device_ready_state_exit(struct sci_base_state_machine *sm)
Dan Williams88f3b622011-04-22 19:18:03 -0700925{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000926 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williamsab2e8f72011-04-27 16:32:45 -0700927 struct domain_device *dev = sci_dev_to_domain(sci_dev);
928
929 if (dev->dev_type == SAS_END_DEV) {
930 struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
Maciej Patelczyk5d937e92011-04-28 22:06:21 +0000931 struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
Dan Williams88f3b622011-04-22 19:18:03 -0700932
Artur Wojcikcc3dbd02011-05-04 07:58:16 +0000933 isci_remote_device_not_ready(scic_to_ihost(scic), idev,
Dan Williams88f3b622011-04-22 19:18:03 -0700934 SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED);
935 }
936}
937
Dan Williams9269e0e2011-05-12 07:42:17 -0700938static void scic_sds_remote_device_resetting_state_enter(struct sci_base_state_machine *sm)
Dan Williams88f3b622011-04-22 19:18:03 -0700939{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000940 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williams88f3b622011-04-22 19:18:03 -0700941
Dan Williams88f3b622011-04-22 19:18:03 -0700942 scic_sds_remote_node_context_suspend(
943 &sci_dev->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
944}
945
Dan Williams9269e0e2011-05-12 07:42:17 -0700946static void scic_sds_remote_device_resetting_state_exit(struct sci_base_state_machine *sm)
Dan Williams88f3b622011-04-22 19:18:03 -0700947{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000948 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williams88f3b622011-04-22 19:18:03 -0700949
950 scic_sds_remote_node_context_resume(&sci_dev->rnc, NULL, NULL);
951}
952
Dan Williams9269e0e2011-05-12 07:42:17 -0700953static void scic_sds_stp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm)
Dan Williamsab2e8f72011-04-27 16:32:45 -0700954{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000955 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williamsab2e8f72011-04-27 16:32:45 -0700956
Dan Williamsab2e8f72011-04-27 16:32:45 -0700957 sci_dev->working_request = NULL;
958 if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) {
959 /*
960 * Since the RNC is ready, it's alright to finish completion
961 * processing (e.g. signal the remote device is ready). */
962 scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(sci_dev);
963 } else {
964 scic_sds_remote_node_context_resume(&sci_dev->rnc,
965 scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler,
966 sci_dev);
967 }
968}
969
Dan Williams9269e0e2011-05-12 07:42:17 -0700970static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm)
Dan Williamsab2e8f72011-04-27 16:32:45 -0700971{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000972 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williamsab2e8f72011-04-27 16:32:45 -0700973 struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
974
975 BUG_ON(sci_dev->working_request == NULL);
976
Artur Wojcikcc3dbd02011-05-04 07:58:16 +0000977 isci_remote_device_not_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev),
Dan Williamsab2e8f72011-04-27 16:32:45 -0700978 SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED);
979}
980
Dan Williams9269e0e2011-05-12 07:42:17 -0700981static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_state_machine *sm)
Dan Williamsab2e8f72011-04-27 16:32:45 -0700982{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000983 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williamsab2e8f72011-04-27 16:32:45 -0700984 struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
985 struct isci_remote_device *idev = sci_dev_to_idev(sci_dev);
986
Dan Williamsab2e8f72011-04-27 16:32:45 -0700987 if (sci_dev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED)
Artur Wojcikcc3dbd02011-05-04 07:58:16 +0000988 isci_remote_device_not_ready(scic_to_ihost(scic), idev,
Dan Williamsab2e8f72011-04-27 16:32:45 -0700989 sci_dev->not_ready_reason);
990}
991
Dan Williams9269e0e2011-05-12 07:42:17 -0700992static void scic_sds_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm)
Dan Williamsab2e8f72011-04-27 16:32:45 -0700993{
Edmund Nadolskie3013702011-06-02 00:10:43 +0000994 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williamsab2e8f72011-04-27 16:32:45 -0700995 struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
996
Artur Wojcikcc3dbd02011-05-04 07:58:16 +0000997 isci_remote_device_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev));
Dan Williamsab2e8f72011-04-27 16:32:45 -0700998}
999
Dan Williams9269e0e2011-05-12 07:42:17 -07001000static void scic_sds_smp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm)
Dan Williamsab2e8f72011-04-27 16:32:45 -07001001{
Edmund Nadolskie3013702011-06-02 00:10:43 +00001002 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williamsab2e8f72011-04-27 16:32:45 -07001003 struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev);
1004
1005 BUG_ON(sci_dev->working_request == NULL);
1006
Artur Wojcikcc3dbd02011-05-04 07:58:16 +00001007 isci_remote_device_not_ready(scic_to_ihost(scic), sci_dev_to_idev(sci_dev),
Dan Williamsab2e8f72011-04-27 16:32:45 -07001008 SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED);
1009}
1010
Dan Williams9269e0e2011-05-12 07:42:17 -07001011static void scic_sds_smp_remote_device_ready_cmd_substate_exit(struct sci_base_state_machine *sm)
Dan Williamsab2e8f72011-04-27 16:32:45 -07001012{
Edmund Nadolskie3013702011-06-02 00:10:43 +00001013 struct scic_sds_remote_device *sci_dev = container_of(sm, typeof(*sci_dev), sm);
Dan Williamsab2e8f72011-04-27 16:32:45 -07001014
1015 sci_dev->working_request = NULL;
1016}
Dan Williams88f3b622011-04-22 19:18:03 -07001017
1018static const struct sci_base_state scic_sds_remote_device_state_table[] = {
Edmund Nadolskie3013702011-06-02 00:10:43 +00001019 [SCI_DEV_INITIAL] = {
Dan Williams88f3b622011-04-22 19:18:03 -07001020 .enter_state = scic_sds_remote_device_initial_state_enter,
1021 },
Edmund Nadolskie3013702011-06-02 00:10:43 +00001022 [SCI_DEV_STOPPED] = {
Dan Williams88f3b622011-04-22 19:18:03 -07001023 .enter_state = scic_sds_remote_device_stopped_state_enter,
1024 },
Edmund Nadolskie3013702011-06-02 00:10:43 +00001025 [SCI_DEV_STARTING] = {
Dan Williams88f3b622011-04-22 19:18:03 -07001026 .enter_state = scic_sds_remote_device_starting_state_enter,
1027 },
Edmund Nadolskie3013702011-06-02 00:10:43 +00001028 [SCI_DEV_READY] = {
Dan Williams88f3b622011-04-22 19:18:03 -07001029 .enter_state = scic_sds_remote_device_ready_state_enter,
1030 .exit_state = scic_sds_remote_device_ready_state_exit
1031 },
Edmund Nadolskie3013702011-06-02 00:10:43 +00001032 [SCI_STP_DEV_IDLE] = {
Dan Williamsab2e8f72011-04-27 16:32:45 -07001033 .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter,
1034 },
Edmund Nadolskie3013702011-06-02 00:10:43 +00001035 [SCI_STP_DEV_CMD] = {
Dan Williamsab2e8f72011-04-27 16:32:45 -07001036 .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter,
1037 },
Edmund Nadolskie3013702011-06-02 00:10:43 +00001038 [SCI_STP_DEV_NCQ] = { },
1039 [SCI_STP_DEV_NCQ_ERROR] = {
Dan Williamsab2e8f72011-04-27 16:32:45 -07001040 .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter,
1041 },
Edmund Nadolskie3013702011-06-02 00:10:43 +00001042 [SCI_STP_DEV_AWAIT_RESET] = { },
1043 [SCI_SMP_DEV_IDLE] = {
Dan Williamsab2e8f72011-04-27 16:32:45 -07001044 .enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter,
1045 },
Edmund Nadolskie3013702011-06-02 00:10:43 +00001046 [SCI_SMP_DEV_CMD] = {
Dan Williamsab2e8f72011-04-27 16:32:45 -07001047 .enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter,
1048 .exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit,
1049 },
Edmund Nadolskie3013702011-06-02 00:10:43 +00001050 [SCI_DEV_STOPPING] = { },
1051 [SCI_DEV_FAILED] = { },
1052 [SCI_DEV_RESETTING] = {
Dan Williams88f3b622011-04-22 19:18:03 -07001053 .enter_state = scic_sds_remote_device_resetting_state_enter,
1054 .exit_state = scic_sds_remote_device_resetting_state_exit
1055 },
Edmund Nadolskie3013702011-06-02 00:10:43 +00001056 [SCI_DEV_FINAL] = { },
Dan Williams88f3b622011-04-22 19:18:03 -07001057};
1058
1059/**
Dan Williamsb87ee302011-04-25 11:48:29 -07001060 * scic_remote_device_construct() - common construction
Dan Williams88f3b622011-04-22 19:18:03 -07001061 * @sci_port: SAS/SATA port through which this device is accessed.
1062 * @sci_dev: remote device to construct
1063 *
Dan Williamsb87ee302011-04-25 11:48:29 -07001064 * This routine just performs benign initialization and does not
1065 * allocate the remote_node_context which is left to
1066 * scic_remote_device_[de]a_construct(). scic_remote_device_destruct()
1067 * frees the remote_node_context(s) for the device.
Dan Williams88f3b622011-04-22 19:18:03 -07001068 */
1069static void scic_remote_device_construct(struct scic_sds_port *sci_port,
1070 struct scic_sds_remote_device *sci_dev)
1071{
1072 sci_dev->owning_port = sci_port;
1073 sci_dev->started_request_count = 0;
Dan Williams88f3b622011-04-22 19:18:03 -07001074
Edmund Nadolski12ef6542011-06-02 00:10:50 +00001075 sci_init_sm(&sci_dev->sm, scic_sds_remote_device_state_table, SCI_DEV_INITIAL);
Dan Williams88f3b622011-04-22 19:18:03 -07001076
1077 scic_sds_remote_node_context_construct(&sci_dev->rnc,
1078 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);
Dan Williams88f3b622011-04-22 19:18:03 -07001079}
1080
1081/**
Dan Williamsb87ee302011-04-25 11:48:29 -07001082 * scic_remote_device_da_construct() - construct direct attached device.
Dan Williams88f3b622011-04-22 19:18:03 -07001083 *
Dan Williamsb87ee302011-04-25 11:48:29 -07001084 * The information (e.g. IAF, Signature FIS, etc.) necessary to build
1085 * the device is known to the SCI Core since it is contained in the
1086 * scic_phy object. Remote node context(s) is/are a global resource
1087 * allocated by this routine, freed by scic_remote_device_destruct().
1088 *
1089 * Returns:
1090 * SCI_FAILURE_DEVICE_EXISTS - device has already been constructed.
1091 * SCI_FAILURE_UNSUPPORTED_PROTOCOL - e.g. sas device attached to
1092 * sata-only controller instance.
1093 * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted.
Dan Williams88f3b622011-04-22 19:18:03 -07001094 */
Dan Williamsb87ee302011-04-25 11:48:29 -07001095static enum sci_status scic_remote_device_da_construct(struct scic_sds_port *sci_port,
1096 struct scic_sds_remote_device *sci_dev)
Dan Williams88f3b622011-04-22 19:18:03 -07001097{
1098 enum sci_status status;
Dan Williamsa1a113b2011-04-21 18:44:45 -07001099 struct domain_device *dev = sci_dev_to_domain(sci_dev);
Dan Williams88f3b622011-04-22 19:18:03 -07001100
Dan Williamsb87ee302011-04-25 11:48:29 -07001101 scic_remote_device_construct(sci_port, sci_dev);
1102
Dan Williams88f3b622011-04-22 19:18:03 -07001103 /*
1104 * This information is request to determine how many remote node context
1105 * entries will be needed to store the remote node.
1106 */
Dan Williams88f3b622011-04-22 19:18:03 -07001107 sci_dev->is_direct_attached = true;
Dan Williamsa1a113b2011-04-21 18:44:45 -07001108 status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller,
1109 sci_dev,
Dan Williamsab2e8f72011-04-27 16:32:45 -07001110 &sci_dev->rnc.remote_node_index);
Dan Williams88f3b622011-04-22 19:18:03 -07001111
Dan Williamsa1a113b2011-04-21 18:44:45 -07001112 if (status != SCI_SUCCESS)
1113 return status;
Dan Williams88f3b622011-04-22 19:18:03 -07001114
Dan Williamsab2e8f72011-04-27 16:32:45 -07001115 if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV ||
1116 (dev->tproto & SAS_PROTOCOL_STP) || dev_is_expander(dev))
1117 /* pass */;
1118 else
Dan Williamsa1a113b2011-04-21 18:44:45 -07001119 return SCI_FAILURE_UNSUPPORTED_PROTOCOL;
Dan Williams88f3b622011-04-22 19:18:03 -07001120
Dan Williamsa1a113b2011-04-21 18:44:45 -07001121 sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed(sci_port);
Dan Williams88f3b622011-04-22 19:18:03 -07001122
Dan Williamsa1a113b2011-04-21 18:44:45 -07001123 /* / @todo Should I assign the port width by reading all of the phys on the port? */
1124 sci_dev->device_port_width = 1;
Dan Williams88f3b622011-04-22 19:18:03 -07001125
Dan Williamsa1a113b2011-04-21 18:44:45 -07001126 return SCI_SUCCESS;
Dan Williams88f3b622011-04-22 19:18:03 -07001127}
1128
Dan Williams88f3b622011-04-22 19:18:03 -07001129/**
Dan Williamsb87ee302011-04-25 11:48:29 -07001130 * scic_remote_device_ea_construct() - construct expander attached device
Dan Williams88f3b622011-04-22 19:18:03 -07001131 *
Dan Williamsb87ee302011-04-25 11:48:29 -07001132 * Remote node context(s) is/are a global resource allocated by this
1133 * routine, freed by scic_remote_device_destruct().
1134 *
1135 * Returns:
1136 * SCI_FAILURE_DEVICE_EXISTS - device has already been constructed.
1137 * SCI_FAILURE_UNSUPPORTED_PROTOCOL - e.g. sas device attached to
1138 * sata-only controller instance.
1139 * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted.
Dan Williams88f3b622011-04-22 19:18:03 -07001140 */
Dan Williamsb87ee302011-04-25 11:48:29 -07001141static enum sci_status scic_remote_device_ea_construct(struct scic_sds_port *sci_port,
Dan Williams00d680e2011-04-25 14:29:29 -07001142 struct scic_sds_remote_device *sci_dev)
Dan Williams88f3b622011-04-22 19:18:03 -07001143{
Dan Williamsa1a113b2011-04-21 18:44:45 -07001144 struct domain_device *dev = sci_dev_to_domain(sci_dev);
Dan Williams88f3b622011-04-22 19:18:03 -07001145 enum sci_status status;
Dan Williams88f3b622011-04-22 19:18:03 -07001146
Dan Williamsb87ee302011-04-25 11:48:29 -07001147 scic_remote_device_construct(sci_port, sci_dev);
Dan Williams88f3b622011-04-22 19:18:03 -07001148
Dan Williamsab2e8f72011-04-27 16:32:45 -07001149 status = scic_sds_controller_allocate_remote_node_context(sci_port->owning_controller,
1150 sci_dev,
1151 &sci_dev->rnc.remote_node_index);
Dan Williamsa1a113b2011-04-21 18:44:45 -07001152 if (status != SCI_SUCCESS)
1153 return status;
Dan Williams88f3b622011-04-22 19:18:03 -07001154
Dan Williamsab2e8f72011-04-27 16:32:45 -07001155 if (dev->dev_type == SAS_END_DEV || dev->dev_type == SATA_DEV ||
1156 (dev->tproto & SAS_PROTOCOL_STP) || dev_is_expander(dev))
1157 /* pass */;
1158 else
1159 return SCI_FAILURE_UNSUPPORTED_PROTOCOL;
Dan Williams88f3b622011-04-22 19:18:03 -07001160
Dan Williamsa1a113b2011-04-21 18:44:45 -07001161 /*
1162 * For SAS-2 the physical link rate is actually a logical link
1163 * rate that incorporates multiplexing. The SCU doesn't
1164 * incorporate multiplexing and for the purposes of the
1165 * connection the logical link rate is that same as the
1166 * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay
1167 * one another, so this code works for both situations. */
1168 sci_dev->connection_rate = min_t(u16, scic_sds_port_get_max_allowed_speed(sci_port),
Dan Williams00d680e2011-04-25 14:29:29 -07001169 dev->linkrate);
Dan Williams88f3b622011-04-22 19:18:03 -07001170
Dan Williamsa1a113b2011-04-21 18:44:45 -07001171 /* / @todo Should I assign the port width by reading all of the phys on the port? */
1172 sci_dev->device_port_width = 1;
Dan Williams88f3b622011-04-22 19:18:03 -07001173
Dan Williamsab2e8f72011-04-27 16:32:45 -07001174 return SCI_SUCCESS;
Dan Williams88f3b622011-04-22 19:18:03 -07001175}
1176
1177/**
1178 * scic_remote_device_start() - This method will start the supplied remote
1179 * device. This method enables normal IO requests to flow through to the
1180 * remote device.
1181 * @remote_device: This parameter specifies the device to be started.
1182 * @timeout: This parameter specifies the number of milliseconds in which the
1183 * start operation should complete.
1184 *
1185 * An indication of whether the device was successfully started. SCI_SUCCESS
1186 * This value is returned if the device was successfully started.
1187 * SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start
1188 * the device when there have been no phys added to it.
1189 */
1190static enum sci_status scic_remote_device_start(struct scic_sds_remote_device *sci_dev,
Dan Williamseb229672011-05-01 14:05:57 -07001191 u32 timeout)
Dan Williams88f3b622011-04-22 19:18:03 -07001192{
Edmund Nadolskie3013702011-06-02 00:10:43 +00001193 struct sci_base_state_machine *sm = &sci_dev->sm;
Dan Williamseb229672011-05-01 14:05:57 -07001194 enum scic_sds_remote_device_states state = sm->current_state_id;
1195 enum sci_status status;
1196
Edmund Nadolskie3013702011-06-02 00:10:43 +00001197 if (state != SCI_DEV_STOPPED) {
Dan Williamseb229672011-05-01 14:05:57 -07001198 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
1199 __func__, state);
1200 return SCI_FAILURE_INVALID_STATE;
1201 }
1202
1203 status = scic_sds_remote_node_context_resume(&sci_dev->rnc,
1204 remote_device_resume_done,
1205 sci_dev);
1206 if (status != SCI_SUCCESS)
1207 return status;
1208
Edmund Nadolskie3013702011-06-02 00:10:43 +00001209 sci_change_state(sm, SCI_DEV_STARTING);
Dan Williamseb229672011-05-01 14:05:57 -07001210
1211 return SCI_SUCCESS;
Dan Williams88f3b622011-04-22 19:18:03 -07001212}
Dan Williams6f231dd2011-07-02 22:56:22 -07001213
Dan Williams00d680e2011-04-25 14:29:29 -07001214static enum sci_status isci_remote_device_construct(struct isci_port *iport,
1215 struct isci_remote_device *idev)
Dan Williams6f231dd2011-07-02 22:56:22 -07001216{
Dan Williamse5313812011-05-07 10:11:43 -07001217 struct scic_sds_port *sci_port = &iport->sci;
Dan Williams00d680e2011-04-25 14:29:29 -07001218 struct isci_host *ihost = iport->isci_host;
1219 struct domain_device *dev = idev->domain_dev;
1220 enum sci_status status;
Dan Williams6f231dd2011-07-02 22:56:22 -07001221
Dan Williams00d680e2011-04-25 14:29:29 -07001222 if (dev->parent && dev_is_expander(dev->parent))
1223 status = scic_remote_device_ea_construct(sci_port, &idev->sci);
1224 else
1225 status = scic_remote_device_da_construct(sci_port, &idev->sci);
Dan Williams6f231dd2011-07-02 22:56:22 -07001226
1227 if (status != SCI_SUCCESS) {
Dan Williams00d680e2011-04-25 14:29:29 -07001228 dev_dbg(&ihost->pdev->dev, "%s: construct failed: %d\n",
1229 __func__, status);
Dan Williams6f231dd2011-07-02 22:56:22 -07001230
1231 return status;
1232 }
1233
Dan Williams6f231dd2011-07-02 22:56:22 -07001234 /* start the device. */
Dan Williams00d680e2011-04-25 14:29:29 -07001235 status = scic_remote_device_start(&idev->sci, ISCI_REMOTE_DEVICE_START_TIMEOUT);
Dan Williams6f231dd2011-07-02 22:56:22 -07001236
Dan Williams00d680e2011-04-25 14:29:29 -07001237 if (status != SCI_SUCCESS)
1238 dev_warn(&ihost->pdev->dev, "remote device start failed: %d\n",
1239 status);
Dan Williams6f231dd2011-07-02 22:56:22 -07001240
1241 return status;
1242}
1243
Dan Williams4393aa42011-03-31 13:10:44 -07001244void isci_remote_device_nuke_requests(struct isci_host *ihost, struct isci_remote_device *idev)
Dan Williams6f231dd2011-07-02 22:56:22 -07001245{
1246 DECLARE_COMPLETION_ONSTACK(aborted_task_completion);
Dan Williams6f231dd2011-07-02 22:56:22 -07001247
Dan Williams4393aa42011-03-31 13:10:44 -07001248 dev_dbg(&ihost->pdev->dev,
1249 "%s: idev = %p\n", __func__, idev);
Dan Williams6f231dd2011-07-02 22:56:22 -07001250
1251 /* Cleanup all requests pending for this device. */
Dan Williams980d3ae2011-06-20 15:11:22 -07001252 isci_terminate_pending_requests(ihost, idev);
Dan Williams6f231dd2011-07-02 22:56:22 -07001253
Dan Williams4393aa42011-03-31 13:10:44 -07001254 dev_dbg(&ihost->pdev->dev,
1255 "%s: idev = %p, done\n", __func__, idev);
Dan Williams6f231dd2011-07-02 22:56:22 -07001256}
1257
Dan Williams6f231dd2011-07-02 22:56:22 -07001258/**
1259 * This function builds the isci_remote_device when a libsas dev_found message
1260 * is received.
1261 * @isci_host: This parameter specifies the isci host object.
1262 * @port: This parameter specifies the isci_port conected to this device.
1263 *
1264 * pointer to new isci_remote_device.
1265 */
1266static struct isci_remote_device *
Dan Williamsd9c37392011-03-03 17:59:32 -08001267isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport)
Dan Williams6f231dd2011-07-02 22:56:22 -07001268{
Dan Williamsd9c37392011-03-03 17:59:32 -08001269 struct isci_remote_device *idev;
1270 int i;
Dan Williams6f231dd2011-07-02 22:56:22 -07001271
Dan Williamsd9c37392011-03-03 17:59:32 -08001272 for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
Dan Williams57f20f42011-04-21 18:14:45 -07001273 idev = &ihost->devices[i];
Dan Williamsd9c37392011-03-03 17:59:32 -08001274 if (!test_and_set_bit(IDEV_ALLOCATED, &idev->flags))
1275 break;
1276 }
Dan Williams6f231dd2011-07-02 22:56:22 -07001277
Dan Williamsd9c37392011-03-03 17:59:32 -08001278 if (i >= SCI_MAX_REMOTE_DEVICES) {
1279 dev_warn(&ihost->pdev->dev, "%s: failed\n", __func__);
Dan Williams6f231dd2011-07-02 22:56:22 -07001280 return NULL;
1281 }
1282
Bartosz Barcinski6cb4d6b2011-04-12 17:28:43 -07001283 if (WARN_ONCE(!list_empty(&idev->reqs_in_process), "found requests in process\n"))
1284 return NULL;
1285
1286 if (WARN_ONCE(!list_empty(&idev->node), "found non-idle remote device\n"))
1287 return NULL;
1288
Dan Williamsd9c37392011-03-03 17:59:32 -08001289 return idev;
Dan Williams6f231dd2011-07-02 22:56:22 -07001290}
Dan Williams6f231dd2011-07-02 22:56:22 -07001291
Dan Williams209fae12011-06-13 17:39:44 -07001292void isci_remote_device_release(struct kref *kref)
1293{
1294 struct isci_remote_device *idev = container_of(kref, typeof(*idev), kref);
1295 struct isci_host *ihost = idev->isci_port->isci_host;
1296
1297 idev->domain_dev = NULL;
1298 idev->isci_port = NULL;
1299 clear_bit(IDEV_START_PENDING, &idev->flags);
1300 clear_bit(IDEV_STOP_PENDING, &idev->flags);
Dan Williamsf2088262011-06-16 11:26:12 -07001301 clear_bit(IDEV_IO_READY, &idev->flags);
Dan Williams209fae12011-06-13 17:39:44 -07001302 clear_bit(IDEV_GONE, &idev->flags);
1303 clear_bit(IDEV_EH, &idev->flags);
1304 smp_mb__before_clear_bit();
1305 clear_bit(IDEV_ALLOCATED, &idev->flags);
1306 wake_up(&ihost->eventq);
1307}
1308
Dan Williams6f231dd2011-07-02 22:56:22 -07001309/**
Dan Williams6f231dd2011-07-02 22:56:22 -07001310 * isci_remote_device_stop() - This function is called internally to stop the
1311 * remote device.
1312 * @isci_host: This parameter specifies the isci host object.
1313 * @isci_device: This parameter specifies the remote device.
1314 *
1315 * The status of the scic request to stop.
1316 */
Dan Williams6ad31fe2011-03-04 12:10:29 -08001317enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_remote_device *idev)
Dan Williams6f231dd2011-07-02 22:56:22 -07001318{
1319 enum sci_status status;
1320 unsigned long flags;
Dan Williams6f231dd2011-07-02 22:56:22 -07001321
Dan Williams6ad31fe2011-03-04 12:10:29 -08001322 dev_dbg(&ihost->pdev->dev,
1323 "%s: isci_device = %p\n", __func__, idev);
Dan Williams6f231dd2011-07-02 22:56:22 -07001324
Dan Williams209fae12011-06-13 17:39:44 -07001325 spin_lock_irqsave(&ihost->scic_lock, flags);
1326 idev->domain_dev->lldd_dev = NULL; /* disable new lookups */
1327 set_bit(IDEV_GONE, &idev->flags);
Dan Williams209fae12011-06-13 17:39:44 -07001328 spin_unlock_irqrestore(&ihost->scic_lock, flags);
Jeff Skirvin6e2802a2011-03-08 20:32:16 -07001329
1330 /* Kill all outstanding requests. */
Dan Williams4393aa42011-03-31 13:10:44 -07001331 isci_remote_device_nuke_requests(ihost, idev);
Jeff Skirvin6e2802a2011-03-08 20:32:16 -07001332
Dan Williams6ad31fe2011-03-04 12:10:29 -08001333 set_bit(IDEV_STOP_PENDING, &idev->flags);
Dan Williams6f231dd2011-07-02 22:56:22 -07001334
Dan Williams6ad31fe2011-03-04 12:10:29 -08001335 spin_lock_irqsave(&ihost->scic_lock, flags);
Dan Williams57f20f42011-04-21 18:14:45 -07001336 status = scic_remote_device_stop(&idev->sci, 50);
Dan Williams6ad31fe2011-03-04 12:10:29 -08001337 spin_unlock_irqrestore(&ihost->scic_lock, flags);
Dan Williams6f231dd2011-07-02 22:56:22 -07001338
1339 /* Wait for the stop complete callback. */
Dan Williams209fae12011-06-13 17:39:44 -07001340 if (WARN_ONCE(status != SCI_SUCCESS, "failed to stop device\n"))
1341 /* nothing to wait for */;
1342 else
Dan Williams6ad31fe2011-03-04 12:10:29 -08001343 wait_for_device_stop(ihost, idev);
Dan Williams6f231dd2011-07-02 22:56:22 -07001344
Dan Williams6f231dd2011-07-02 22:56:22 -07001345 return status;
1346}
1347
1348/**
1349 * isci_remote_device_gone() - This function is called by libsas when a domain
1350 * device is removed.
1351 * @domain_device: This parameter specifies the libsas domain device.
1352 *
1353 */
Dan Williams6ad31fe2011-03-04 12:10:29 -08001354void isci_remote_device_gone(struct domain_device *dev)
Dan Williams6f231dd2011-07-02 22:56:22 -07001355{
Dan Williams4393aa42011-03-31 13:10:44 -07001356 struct isci_host *ihost = dev_to_ihost(dev);
Dan Williams6ad31fe2011-03-04 12:10:29 -08001357 struct isci_remote_device *idev = dev->lldd_dev;
Dan Williams6f231dd2011-07-02 22:56:22 -07001358
Dan Williams6ad31fe2011-03-04 12:10:29 -08001359 dev_dbg(&ihost->pdev->dev,
Dan Williams6f231dd2011-07-02 22:56:22 -07001360 "%s: domain_device = %p, isci_device = %p, isci_port = %p\n",
Dan Williams6ad31fe2011-03-04 12:10:29 -08001361 __func__, dev, idev, idev->isci_port);
Dan Williams6f231dd2011-07-02 22:56:22 -07001362
Dan Williams6ad31fe2011-03-04 12:10:29 -08001363 isci_remote_device_stop(ihost, idev);
Dan Williams6f231dd2011-07-02 22:56:22 -07001364}
1365
1366
1367/**
1368 * isci_remote_device_found() - This function is called by libsas when a remote
1369 * device is discovered. A remote device object is created and started. the
1370 * function then sleeps until the sci core device started message is
1371 * received.
1372 * @domain_device: This parameter specifies the libsas domain device.
1373 *
1374 * status, zero indicates success.
1375 */
1376int isci_remote_device_found(struct domain_device *domain_dev)
1377{
Dan Williams4393aa42011-03-31 13:10:44 -07001378 struct isci_host *isci_host = dev_to_ihost(domain_dev);
Dan Williams6f231dd2011-07-02 22:56:22 -07001379 struct isci_port *isci_port;
1380 struct isci_phy *isci_phy;
1381 struct asd_sas_port *sas_port;
1382 struct asd_sas_phy *sas_phy;
1383 struct isci_remote_device *isci_device;
1384 enum sci_status status;
Dan Williams6f231dd2011-07-02 22:56:22 -07001385
Dan Williams6f231dd2011-07-02 22:56:22 -07001386 dev_dbg(&isci_host->pdev->dev,
1387 "%s: domain_device = %p\n", __func__, domain_dev);
1388
Dan Williams0cf89d12011-02-18 09:25:07 -08001389 wait_for_start(isci_host);
1390
Dan Williams6f231dd2011-07-02 22:56:22 -07001391 sas_port = domain_dev->port;
1392 sas_phy = list_first_entry(&sas_port->phy_list, struct asd_sas_phy,
1393 port_phy_el);
1394 isci_phy = to_isci_phy(sas_phy);
1395 isci_port = isci_phy->isci_port;
1396
1397 /* we are being called for a device on this port,
1398 * so it has to come up eventually
1399 */
1400 wait_for_completion(&isci_port->start_complete);
1401
1402 if ((isci_stopping == isci_port_get_state(isci_port)) ||
1403 (isci_stopped == isci_port_get_state(isci_port)))
1404 return -ENODEV;
1405
1406 isci_device = isci_remote_device_alloc(isci_host, isci_port);
Dan Williamsd9c37392011-03-03 17:59:32 -08001407 if (!isci_device)
1408 return -ENODEV;
Dan Williams6f231dd2011-07-02 22:56:22 -07001409
Dan Williams209fae12011-06-13 17:39:44 -07001410 kref_init(&isci_device->kref);
Dan Williams6f231dd2011-07-02 22:56:22 -07001411 INIT_LIST_HEAD(&isci_device->node);
Dan Williams209fae12011-06-13 17:39:44 -07001412
1413 spin_lock_irq(&isci_host->scic_lock);
Dan Williams6f231dd2011-07-02 22:56:22 -07001414 isci_device->domain_dev = domain_dev;
1415 isci_device->isci_port = isci_port;
Dan Williams6f231dd2011-07-02 22:56:22 -07001416 list_add_tail(&isci_device->node, &isci_port->remote_dev_list);
1417
Dan Williams6ad31fe2011-03-04 12:10:29 -08001418 set_bit(IDEV_START_PENDING, &isci_device->flags);
Dan Williams6f231dd2011-07-02 22:56:22 -07001419 status = isci_remote_device_construct(isci_port, isci_device);
Dan Williams6f231dd2011-07-02 22:56:22 -07001420
Dan Williams6f231dd2011-07-02 22:56:22 -07001421 dev_dbg(&isci_host->pdev->dev,
1422 "%s: isci_device = %p\n",
1423 __func__, isci_device);
1424
Dan Williams209fae12011-06-13 17:39:44 -07001425 if (status == SCI_SUCCESS) {
1426 /* device came up, advertise it to the world */
1427 domain_dev->lldd_dev = isci_device;
1428 } else
1429 isci_put_device(isci_device);
1430 spin_unlock_irq(&isci_host->scic_lock);
Dan Williams6f231dd2011-07-02 22:56:22 -07001431
Dan Williams6ad31fe2011-03-04 12:10:29 -08001432 /* wait for the device ready callback. */
1433 wait_for_device_start(isci_host, isci_device);
1434
Dan Williams209fae12011-06-13 17:39:44 -07001435 return status == SCI_SUCCESS ? 0 : -ENODEV;
Dan Williams6f231dd2011-07-02 22:56:22 -07001436}
1437/**
1438 * isci_device_is_reset_pending() - This function will check if there is any
1439 * pending reset condition on the device.
1440 * @request: This parameter is the isci_device object.
1441 *
1442 * true if there is a reset pending for the device.
1443 */
1444bool isci_device_is_reset_pending(
1445 struct isci_host *isci_host,
1446 struct isci_remote_device *isci_device)
1447{
1448 struct isci_request *isci_request;
1449 struct isci_request *tmp_req;
1450 bool reset_is_pending = false;
1451 unsigned long flags;
1452
1453 dev_dbg(&isci_host->pdev->dev,
1454 "%s: isci_device = %p\n", __func__, isci_device);
1455
1456 spin_lock_irqsave(&isci_host->scic_lock, flags);
1457
1458 /* Check for reset on all pending requests. */
1459 list_for_each_entry_safe(isci_request, tmp_req,
1460 &isci_device->reqs_in_process, dev_node) {
1461 dev_dbg(&isci_host->pdev->dev,
1462 "%s: isci_device = %p request = %p\n",
1463 __func__, isci_device, isci_request);
1464
1465 if (isci_request->ttype == io_task) {
Dan Williams6f231dd2011-07-02 22:56:22 -07001466 struct sas_task *task = isci_request_access_task(
1467 isci_request);
1468
Bartosz Barcinski467e8552011-04-12 17:28:41 -07001469 spin_lock(&task->task_state_lock);
Dan Williams6f231dd2011-07-02 22:56:22 -07001470 if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
1471 reset_is_pending = true;
Bartosz Barcinski467e8552011-04-12 17:28:41 -07001472 spin_unlock(&task->task_state_lock);
Dan Williams6f231dd2011-07-02 22:56:22 -07001473 }
1474 }
1475
1476 spin_unlock_irqrestore(&isci_host->scic_lock, flags);
1477
1478 dev_dbg(&isci_host->pdev->dev,
1479 "%s: isci_device = %p reset_is_pending = %d\n",
1480 __func__, isci_device, reset_is_pending);
1481
1482 return reset_is_pending;
1483}
1484
1485/**
1486 * isci_device_clear_reset_pending() - This function will clear if any pending
1487 * reset condition flags on the device.
1488 * @request: This parameter is the isci_device object.
1489 *
1490 * true if there is a reset pending for the device.
1491 */
Dan Williams4393aa42011-03-31 13:10:44 -07001492void isci_device_clear_reset_pending(struct isci_host *ihost, struct isci_remote_device *idev)
Dan Williams6f231dd2011-07-02 22:56:22 -07001493{
1494 struct isci_request *isci_request;
1495 struct isci_request *tmp_req;
Dan Williams6f231dd2011-07-02 22:56:22 -07001496 unsigned long flags = 0;
1497
Dan Williams4393aa42011-03-31 13:10:44 -07001498 dev_dbg(&ihost->pdev->dev, "%s: idev=%p, ihost=%p\n",
1499 __func__, idev, ihost);
Dan Williams6f231dd2011-07-02 22:56:22 -07001500
Dan Williams4393aa42011-03-31 13:10:44 -07001501 spin_lock_irqsave(&ihost->scic_lock, flags);
Dan Williams6f231dd2011-07-02 22:56:22 -07001502
1503 /* Clear reset pending on all pending requests. */
1504 list_for_each_entry_safe(isci_request, tmp_req,
Dan Williams4393aa42011-03-31 13:10:44 -07001505 &idev->reqs_in_process, dev_node) {
1506 dev_dbg(&ihost->pdev->dev, "%s: idev = %p request = %p\n",
1507 __func__, idev, isci_request);
Dan Williams6f231dd2011-07-02 22:56:22 -07001508
1509 if (isci_request->ttype == io_task) {
1510
1511 unsigned long flags2;
1512 struct sas_task *task = isci_request_access_task(
1513 isci_request);
1514
1515 spin_lock_irqsave(&task->task_state_lock, flags2);
1516 task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
1517 spin_unlock_irqrestore(&task->task_state_lock, flags2);
1518 }
1519 }
Dan Williams4393aa42011-03-31 13:10:44 -07001520 spin_unlock_irqrestore(&ihost->scic_lock, flags);
Dan Williams6f231dd2011-07-02 22:56:22 -07001521}