1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55#include <scsi/sas_ata.h>
56#include "host.h"
57#include "isci.h"
58#include "remote_device.h"
59#include "remote_node_context.h"
60#include "scu_event_codes.h"
61#include "scu_task_context.h"
62
63#undef C
64#define C(a) (#a)
65const char *rnc_state_name(enum scis_sds_remote_node_context_states state)
66{
67 static const char * const strings[] = RNC_STATES;
68
69 if (state >= ARRAY_SIZE(strings))
70 return "UNKNOWN";
71
72 return strings[state];
73}
74#undef C
75
76
77
78
79
80
81
82
83
84bool sci_remote_node_context_is_ready(
85 struct sci_remote_node_context *sci_rnc)
86{
87 u32 current_state = sci_rnc->sm.current_state_id;
88
89 if (current_state == SCI_RNC_READY) {
90 return true;
91 }
92
93 return false;
94}
95
96bool sci_remote_node_context_is_suspended(struct sci_remote_node_context *sci_rnc)
97{
98 u32 current_state = sci_rnc->sm.current_state_id;
99
100 if (current_state == SCI_RNC_TX_RX_SUSPENDED)
101 return true;
102 return false;
103}
104
105static union scu_remote_node_context *sci_rnc_by_id(struct isci_host *ihost, u16 id)
106{
107 if (id < ihost->remote_node_entries &&
108 ihost->device_table[id])
109 return &ihost->remote_node_context_table[id];
110
111 return NULL;
112}
113
114static void sci_remote_node_context_construct_buffer(struct sci_remote_node_context *sci_rnc)
115{
116 struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
117 struct domain_device *dev = idev->domain_dev;
118 int rni = sci_rnc->remote_node_index;
119 union scu_remote_node_context *rnc;
120 struct isci_host *ihost;
121 __le64 sas_addr;
122
123 ihost = idev->owning_port->owning_controller;
124 rnc = sci_rnc_by_id(ihost, rni);
125
126 memset(rnc, 0, sizeof(union scu_remote_node_context)
127 * sci_remote_device_node_count(idev));
128
129 rnc->ssp.remote_node_index = rni;
130 rnc->ssp.remote_node_port_width = idev->device_port_width;
131 rnc->ssp.logical_port_index = idev->owning_port->physical_port_index;
132
133
134 sas_addr = cpu_to_le64(SAS_ADDR(dev->sas_addr));
135 rnc->ssp.remote_sas_address_hi = upper_32_bits(sas_addr);
136 rnc->ssp.remote_sas_address_lo = lower_32_bits(sas_addr);
137
138 rnc->ssp.nexus_loss_timer_enable = true;
139 rnc->ssp.check_bit = false;
140 rnc->ssp.is_valid = false;
141 rnc->ssp.is_remote_node_context = true;
142 rnc->ssp.function_number = 0;
143
144 rnc->ssp.arbitration_wait_time = 0;
145
146 if (dev_is_sata(dev)) {
147 rnc->ssp.connection_occupancy_timeout =
148 ihost->user_parameters.stp_max_occupancy_timeout;
149 rnc->ssp.connection_inactivity_timeout =
150 ihost->user_parameters.stp_inactivity_timeout;
151 } else {
152 rnc->ssp.connection_occupancy_timeout =
153 ihost->user_parameters.ssp_max_occupancy_timeout;
154 rnc->ssp.connection_inactivity_timeout =
155 ihost->user_parameters.ssp_inactivity_timeout;
156 }
157
158 rnc->ssp.initial_arbitration_wait_time = 0;
159
160
161 rnc->ssp.oaf_connection_rate = idev->connection_rate;
162 rnc->ssp.oaf_features = 0;
163 rnc->ssp.oaf_source_zone_group = 0;
164 rnc->ssp.oaf_more_compatibility_features = 0;
165}
166
167
168
169
170
171
172
173
174
175
176static void sci_remote_node_context_setup_to_resume(
177 struct sci_remote_node_context *sci_rnc,
178 scics_sds_remote_node_context_callback callback,
179 void *callback_parameter,
180 enum sci_remote_node_context_destination_state dest_param)
181{
182 if (sci_rnc->destination_state != RNC_DEST_FINAL) {
183 sci_rnc->destination_state = dest_param;
184 if (callback != NULL) {
185 sci_rnc->user_callback = callback;
186 sci_rnc->user_cookie = callback_parameter;
187 }
188 }
189}
190
191static void sci_remote_node_context_setup_to_destroy(
192 struct sci_remote_node_context *sci_rnc,
193 scics_sds_remote_node_context_callback callback,
194 void *callback_parameter)
195{
196 struct isci_host *ihost = idev_to_ihost(rnc_to_dev(sci_rnc));
197
198 sci_rnc->destination_state = RNC_DEST_FINAL;
199 sci_rnc->user_callback = callback;
200 sci_rnc->user_cookie = callback_parameter;
201
202 wake_up(&ihost->eventq);
203}
204
205
206
207
208
209
210
211static void sci_remote_node_context_notify_user(
212 struct sci_remote_node_context *rnc)
213{
214 if (rnc->user_callback != NULL) {
215 (*rnc->user_callback)(rnc->user_cookie);
216
217 rnc->user_callback = NULL;
218 rnc->user_cookie = NULL;
219 }
220}
221
222static void sci_remote_node_context_continue_state_transitions(struct sci_remote_node_context *rnc)
223{
224 switch (rnc->destination_state) {
225 case RNC_DEST_READY:
226 case RNC_DEST_SUSPENDED_RESUME:
227 rnc->destination_state = RNC_DEST_READY;
228
229 case RNC_DEST_FINAL:
230 sci_remote_node_context_resume(rnc, rnc->user_callback,
231 rnc->user_cookie);
232 break;
233 default:
234 rnc->destination_state = RNC_DEST_UNSPECIFIED;
235 break;
236 }
237}
238
239static void sci_remote_node_context_validate_context_buffer(struct sci_remote_node_context *sci_rnc)
240{
241 union scu_remote_node_context *rnc_buffer;
242 struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
243 struct domain_device *dev = idev->domain_dev;
244 struct isci_host *ihost = idev->owning_port->owning_controller;
245
246 rnc_buffer = sci_rnc_by_id(ihost, sci_rnc->remote_node_index);
247
248 rnc_buffer->ssp.is_valid = true;
249
250 if (dev_is_sata(dev) && dev->parent) {
251 sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_96);
252 } else {
253 sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_32);
254
255 if (!dev->parent)
256 sci_port_setup_transports(idev->owning_port,
257 sci_rnc->remote_node_index);
258 }
259}
260
261static void sci_remote_node_context_invalidate_context_buffer(struct sci_remote_node_context *sci_rnc)
262{
263 union scu_remote_node_context *rnc_buffer;
264 struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
265 struct isci_host *ihost = idev->owning_port->owning_controller;
266
267 rnc_buffer = sci_rnc_by_id(ihost, sci_rnc->remote_node_index);
268
269 rnc_buffer->ssp.is_valid = false;
270
271 sci_remote_device_post_request(rnc_to_dev(sci_rnc),
272 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE);
273}
274
275static void sci_remote_node_context_initial_state_enter(struct sci_base_state_machine *sm)
276{
277 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
278 struct isci_remote_device *idev = rnc_to_dev(rnc);
279 struct isci_host *ihost = idev->owning_port->owning_controller;
280
281
282
283
284 if (sm->previous_state_id == SCI_RNC_INVALIDATING) {
285 rnc->destination_state = RNC_DEST_UNSPECIFIED;
286 sci_remote_node_context_notify_user(rnc);
287
288 smp_wmb();
289 wake_up(&ihost->eventq);
290 }
291}
292
293static void sci_remote_node_context_posting_state_enter(struct sci_base_state_machine *sm)
294{
295 struct sci_remote_node_context *sci_rnc = container_of(sm, typeof(*sci_rnc), sm);
296
297 sci_remote_node_context_validate_context_buffer(sci_rnc);
298}
299
300static void sci_remote_node_context_invalidating_state_enter(struct sci_base_state_machine *sm)
301{
302 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
303
304
305 sci_remote_device_terminate_requests(rnc_to_dev(rnc));
306 sci_remote_node_context_invalidate_context_buffer(rnc);
307}
308
309static void sci_remote_node_context_resuming_state_enter(struct sci_base_state_machine *sm)
310{
311 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
312 struct isci_remote_device *idev;
313 struct domain_device *dev;
314
315 idev = rnc_to_dev(rnc);
316 dev = idev->domain_dev;
317
318
319
320
321
322
323
324 if (dev_is_sata(dev) && !dev->parent)
325 sci_port_setup_transports(idev->owning_port, rnc->remote_node_index);
326
327 sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME);
328}
329
330static void sci_remote_node_context_ready_state_enter(struct sci_base_state_machine *sm)
331{
332 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
333 enum sci_remote_node_context_destination_state dest_select;
334 int tell_user = 1;
335
336 dest_select = rnc->destination_state;
337 rnc->destination_state = RNC_DEST_UNSPECIFIED;
338
339 if ((dest_select == RNC_DEST_SUSPENDED) ||
340 (dest_select == RNC_DEST_SUSPENDED_RESUME)) {
341 sci_remote_node_context_suspend(
342 rnc, rnc->suspend_reason,
343 SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT);
344
345 if (dest_select == RNC_DEST_SUSPENDED_RESUME)
346 tell_user = 0;
347 }
348 if (tell_user)
349 sci_remote_node_context_notify_user(rnc);
350}
351
352static void sci_remote_node_context_tx_suspended_state_enter(struct sci_base_state_machine *sm)
353{
354 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
355
356 sci_remote_node_context_continue_state_transitions(rnc);
357}
358
359static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm)
360{
361 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
362 struct isci_remote_device *idev = rnc_to_dev(rnc);
363 struct isci_host *ihost = idev->owning_port->owning_controller;
364 u32 new_count = rnc->suspend_count + 1;
365
366 if (new_count == 0)
367 rnc->suspend_count = 1;
368 else
369 rnc->suspend_count = new_count;
370 smp_wmb();
371
372
373 sci_remote_device_abort_requests_pending_abort(idev);
374
375 wake_up(&ihost->eventq);
376 sci_remote_node_context_continue_state_transitions(rnc);
377}
378
379static void sci_remote_node_context_await_suspend_state_exit(
380 struct sci_base_state_machine *sm)
381{
382 struct sci_remote_node_context *rnc
383 = container_of(sm, typeof(*rnc), sm);
384 struct isci_remote_device *idev = rnc_to_dev(rnc);
385
386 if (dev_is_sata(idev->domain_dev))
387 isci_dev_set_hang_detection_timeout(idev, 0);
388}
389
390static const struct sci_base_state sci_remote_node_context_state_table[] = {
391 [SCI_RNC_INITIAL] = {
392 .enter_state = sci_remote_node_context_initial_state_enter,
393 },
394 [SCI_RNC_POSTING] = {
395 .enter_state = sci_remote_node_context_posting_state_enter,
396 },
397 [SCI_RNC_INVALIDATING] = {
398 .enter_state = sci_remote_node_context_invalidating_state_enter,
399 },
400 [SCI_RNC_RESUMING] = {
401 .enter_state = sci_remote_node_context_resuming_state_enter,
402 },
403 [SCI_RNC_READY] = {
404 .enter_state = sci_remote_node_context_ready_state_enter,
405 },
406 [SCI_RNC_TX_SUSPENDED] = {
407 .enter_state = sci_remote_node_context_tx_suspended_state_enter,
408 },
409 [SCI_RNC_TX_RX_SUSPENDED] = {
410 .enter_state = sci_remote_node_context_tx_rx_suspended_state_enter,
411 },
412 [SCI_RNC_AWAIT_SUSPENSION] = {
413 .exit_state = sci_remote_node_context_await_suspend_state_exit,
414 },
415};
416
417void sci_remote_node_context_construct(struct sci_remote_node_context *rnc,
418 u16 remote_node_index)
419{
420 memset(rnc, 0, sizeof(struct sci_remote_node_context));
421
422 rnc->remote_node_index = remote_node_index;
423 rnc->destination_state = RNC_DEST_UNSPECIFIED;
424
425 sci_init_sm(&rnc->sm, sci_remote_node_context_state_table, SCI_RNC_INITIAL);
426}
427
428enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_context *sci_rnc,
429 u32 event_code)
430{
431 enum scis_sds_remote_node_context_states state;
432 u32 next_state;
433
434 state = sci_rnc->sm.current_state_id;
435 switch (state) {
436 case SCI_RNC_POSTING:
437 switch (scu_get_event_code(event_code)) {
438 case SCU_EVENT_POST_RNC_COMPLETE:
439 sci_change_state(&sci_rnc->sm, SCI_RNC_READY);
440 break;
441 default:
442 goto out;
443 }
444 break;
445 case SCI_RNC_INVALIDATING:
446 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) {
447 if (sci_rnc->destination_state == RNC_DEST_FINAL)
448 next_state = SCI_RNC_INITIAL;
449 else
450 next_state = SCI_RNC_POSTING;
451 sci_change_state(&sci_rnc->sm, next_state);
452 } else {
453 switch (scu_get_event_type(event_code)) {
454 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
455 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
456
457
458 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
459 "%s: SCIC Remote Node Context 0x%p was "
460 "suspended by hardware while being "
461 "invalidated.\n", __func__, sci_rnc);
462 break;
463 default:
464 goto out;
465 }
466 }
467 break;
468 case SCI_RNC_RESUMING:
469 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) {
470 sci_change_state(&sci_rnc->sm, SCI_RNC_READY);
471 } else {
472 switch (scu_get_event_type(event_code)) {
473 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
474 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
475
476
477 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
478 "%s: SCIC Remote Node Context 0x%p was "
479 "suspended by hardware while being resumed.\n",
480 __func__, sci_rnc);
481 break;
482 default:
483 goto out;
484 }
485 }
486 break;
487 case SCI_RNC_READY:
488 switch (scu_get_event_type(event_code)) {
489 case SCU_EVENT_TL_RNC_SUSPEND_TX:
490 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED);
491 sci_rnc->suspend_type = scu_get_event_type(event_code);
492 break;
493 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
494 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED);
495 sci_rnc->suspend_type = scu_get_event_type(event_code);
496 break;
497 default:
498 goto out;
499 }
500 break;
501 case SCI_RNC_AWAIT_SUSPENSION:
502 switch (scu_get_event_type(event_code)) {
503 case SCU_EVENT_TL_RNC_SUSPEND_TX:
504 next_state = SCI_RNC_TX_SUSPENDED;
505 break;
506 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
507 next_state = SCI_RNC_TX_RX_SUSPENDED;
508 break;
509 default:
510 goto out;
511 }
512 if (sci_rnc->suspend_type == scu_get_event_type(event_code))
513 sci_change_state(&sci_rnc->sm, next_state);
514 break;
515 default:
516 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
517 "%s: invalid state: %s\n", __func__,
518 rnc_state_name(state));
519 return SCI_FAILURE_INVALID_STATE;
520 }
521 return SCI_SUCCESS;
522
523 out:
524 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
525 "%s: code: %#x state: %s\n", __func__, event_code,
526 rnc_state_name(state));
527 return SCI_FAILURE;
528
529}
530
531enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context *sci_rnc,
532 scics_sds_remote_node_context_callback cb_fn,
533 void *cb_p)
534{
535 enum scis_sds_remote_node_context_states state;
536
537 state = sci_rnc->sm.current_state_id;
538 switch (state) {
539 case SCI_RNC_INVALIDATING:
540 sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p);
541 return SCI_SUCCESS;
542 case SCI_RNC_POSTING:
543 case SCI_RNC_RESUMING:
544 case SCI_RNC_READY:
545 case SCI_RNC_TX_SUSPENDED:
546 case SCI_RNC_TX_RX_SUSPENDED:
547 sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p);
548 sci_change_state(&sci_rnc->sm, SCI_RNC_INVALIDATING);
549 return SCI_SUCCESS;
550 case SCI_RNC_AWAIT_SUSPENSION:
551 sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p);
552 return SCI_SUCCESS;
553 case SCI_RNC_INITIAL:
554 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
555 "%s: invalid state: %s\n", __func__,
556 rnc_state_name(state));
557
558
559
560
561 return SCI_SUCCESS;
562 default:
563 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
564 "%s: invalid state %s\n", __func__,
565 rnc_state_name(state));
566 return SCI_FAILURE_INVALID_STATE;
567 }
568}
569
570enum sci_status sci_remote_node_context_suspend(
571 struct sci_remote_node_context *sci_rnc,
572 enum sci_remote_node_suspension_reasons suspend_reason,
573 u32 suspend_type)
574{
575 enum scis_sds_remote_node_context_states state
576 = sci_rnc->sm.current_state_id;
577 struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
578 enum sci_status status = SCI_FAILURE_INVALID_STATE;
579 enum sci_remote_node_context_destination_state dest_param =
580 RNC_DEST_UNSPECIFIED;
581
582 dev_dbg(scirdev_to_dev(idev),
583 "%s: current state %s, current suspend_type %x dest state %d,"
584 " arg suspend_reason %d, arg suspend_type %x",
585 __func__, rnc_state_name(state), sci_rnc->suspend_type,
586 sci_rnc->destination_state, suspend_reason,
587 suspend_type);
588
589
590 if ((suspend_reason == SCI_HW_SUSPEND) ||
591 (sci_rnc->destination_state == RNC_DEST_FINAL))
592 dest_param = sci_rnc->destination_state;
593
594 switch (state) {
595 case SCI_RNC_READY:
596 break;
597 case SCI_RNC_INVALIDATING:
598 if (sci_rnc->destination_state == RNC_DEST_FINAL) {
599 dev_warn(scirdev_to_dev(idev),
600 "%s: already destroying %p\n",
601 __func__, sci_rnc);
602 return SCI_FAILURE_INVALID_STATE;
603 }
604
605 case SCI_RNC_RESUMING:
606
607 case SCI_RNC_POSTING:
608
609
610
611
612 if (sci_rnc->destination_state != RNC_DEST_FINAL)
613 sci_rnc->destination_state = RNC_DEST_SUSPENDED;
614 sci_rnc->suspend_type = suspend_type;
615 sci_rnc->suspend_reason = suspend_reason;
616 return SCI_SUCCESS;
617
618 case SCI_RNC_TX_SUSPENDED:
619 if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX)
620 status = SCI_SUCCESS;
621 break;
622 case SCI_RNC_TX_RX_SUSPENDED:
623 if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
624 status = SCI_SUCCESS;
625 break;
626 case SCI_RNC_AWAIT_SUSPENSION:
627 if ((sci_rnc->suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
628 || (suspend_type == sci_rnc->suspend_type))
629 return SCI_SUCCESS;
630 break;
631 default:
632 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
633 "%s: invalid state %s\n", __func__,
634 rnc_state_name(state));
635 return SCI_FAILURE_INVALID_STATE;
636 }
637 sci_rnc->destination_state = dest_param;
638 sci_rnc->suspend_type = suspend_type;
639 sci_rnc->suspend_reason = suspend_reason;
640
641 if (status == SCI_SUCCESS) {
642 struct isci_host *ihost = idev->owning_port->owning_controller;
643
644 wake_up_all(&ihost->eventq);
645 return SCI_SUCCESS;
646 }
647 if ((suspend_reason == SCI_SW_SUSPEND_NORMAL) ||
648 (suspend_reason == SCI_SW_SUSPEND_LINKHANG_DETECT)) {
649
650 if (suspend_reason == SCI_SW_SUSPEND_LINKHANG_DETECT)
651 isci_dev_set_hang_detection_timeout(idev, 0x00000001);
652
653 sci_remote_device_post_request(
654 idev, SCI_SOFTWARE_SUSPEND_CMD);
655 }
656 if (state != SCI_RNC_AWAIT_SUSPENSION)
657 sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);
658
659 return SCI_SUCCESS;
660}
661
662enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *sci_rnc,
663 scics_sds_remote_node_context_callback cb_fn,
664 void *cb_p)
665{
666 enum scis_sds_remote_node_context_states state;
667 struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
668
669 state = sci_rnc->sm.current_state_id;
670 dev_dbg(scirdev_to_dev(idev),
671 "%s: state %s, cb_fn = %p, cb_p = %p; dest_state = %d; "
672 "dev resume path %s\n",
673 __func__, rnc_state_name(state), cb_fn, cb_p,
674 sci_rnc->destination_state,
675 test_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags)
676 ? "<abort active>" : "<normal>");
677
678 switch (state) {
679 case SCI_RNC_INITIAL:
680 if (sci_rnc->remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
681 return SCI_FAILURE_INVALID_STATE;
682
683 sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p,
684 RNC_DEST_READY);
685 if (!test_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags)) {
686 sci_remote_node_context_construct_buffer(sci_rnc);
687 sci_change_state(&sci_rnc->sm, SCI_RNC_POSTING);
688 }
689 return SCI_SUCCESS;
690
691 case SCI_RNC_POSTING:
692 case SCI_RNC_INVALIDATING:
693 case SCI_RNC_RESUMING:
694
695
696
697 switch (sci_rnc->destination_state) {
698 case RNC_DEST_SUSPENDED:
699 case RNC_DEST_SUSPENDED_RESUME:
700
701
702
703 sci_remote_node_context_setup_to_resume(
704 sci_rnc, cb_fn, cb_p,
705 RNC_DEST_SUSPENDED_RESUME);
706 break;
707 default:
708 sci_remote_node_context_setup_to_resume(
709 sci_rnc, cb_fn, cb_p,
710 RNC_DEST_READY);
711 break;
712 }
713 return SCI_SUCCESS;
714
715 case SCI_RNC_TX_SUSPENDED:
716 case SCI_RNC_TX_RX_SUSPENDED:
717 {
718 struct domain_device *dev = idev->domain_dev;
719
720
721
722
723
724 sci_remote_node_context_setup_to_resume(
725 sci_rnc, cb_fn, cb_p, RNC_DEST_READY);
726
727 if (!test_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags)) {
728 if ((dev_is_sata(dev) && dev->parent) ||
729 (sci_rnc->destination_state == RNC_DEST_FINAL))
730 sci_change_state(&sci_rnc->sm,
731 SCI_RNC_INVALIDATING);
732 else
733 sci_change_state(&sci_rnc->sm,
734 SCI_RNC_RESUMING);
735 }
736 }
737 return SCI_SUCCESS;
738
739 case SCI_RNC_AWAIT_SUSPENSION:
740 sci_remote_node_context_setup_to_resume(
741 sci_rnc, cb_fn, cb_p, RNC_DEST_SUSPENDED_RESUME);
742 return SCI_SUCCESS;
743 default:
744 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
745 "%s: invalid state %s\n", __func__,
746 rnc_state_name(state));
747 return SCI_FAILURE_INVALID_STATE;
748 }
749}
750
751enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc,
752 struct isci_request *ireq)
753{
754 enum scis_sds_remote_node_context_states state;
755
756 state = sci_rnc->sm.current_state_id;
757
758 switch (state) {
759 case SCI_RNC_READY:
760 return SCI_SUCCESS;
761 case SCI_RNC_TX_SUSPENDED:
762 case SCI_RNC_TX_RX_SUSPENDED:
763 case SCI_RNC_AWAIT_SUSPENSION:
764 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
765 "%s: invalid state %s\n", __func__,
766 rnc_state_name(state));
767 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
768 default:
769 dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)),
770 "%s: invalid state %s\n", __func__,
771 rnc_state_name(state));
772 return SCI_FAILURE_INVALID_STATE;
773 }
774}
775
776enum sci_status sci_remote_node_context_start_task(
777 struct sci_remote_node_context *sci_rnc,
778 struct isci_request *ireq,
779 scics_sds_remote_node_context_callback cb_fn,
780 void *cb_p)
781{
782 enum sci_status status = sci_remote_node_context_resume(sci_rnc,
783 cb_fn, cb_p);
784 if (status != SCI_SUCCESS)
785 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
786 "%s: resume failed: %d\n", __func__, status);
787 return status;
788}
789
790int sci_remote_node_context_is_safe_to_abort(
791 struct sci_remote_node_context *sci_rnc)
792{
793 enum scis_sds_remote_node_context_states state;
794
795 state = sci_rnc->sm.current_state_id;
796 switch (state) {
797 case SCI_RNC_INVALIDATING:
798 case SCI_RNC_TX_RX_SUSPENDED:
799 return 1;
800 case SCI_RNC_POSTING:
801 case SCI_RNC_RESUMING:
802 case SCI_RNC_READY:
803 case SCI_RNC_TX_SUSPENDED:
804 case SCI_RNC_AWAIT_SUSPENSION:
805 case SCI_RNC_INITIAL:
806 return 0;
807 default:
808 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
809 "%s: invalid state %d\n", __func__, state);
810 return 0;
811 }
812}
813