Print this page
XXXX introduce drv_sectohz
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/comstar/port/pppt/pppt_tgt.c
+++ new/usr/src/uts/common/io/comstar/port/pppt/pppt_tgt.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 #include <sys/cpuvar.h>
26 26 #include <sys/types.h>
27 27 #include <sys/conf.h>
28 28 #include <sys/file.h>
29 29 #include <sys/ddi.h>
30 30 #include <sys/sunddi.h>
31 31 #include <sys/modctl.h>
32 32 #include <sys/sysmacros.h>
33 33
34 34 #include <sys/socket.h>
35 35 #include <sys/strsubr.h>
36 36 #include <sys/door.h>
37 37 #include <sys/note.h>
38 38 #include <sys/sdt.h>
39 39
40 40 #include <sys/stmf.h>
41 41 #include <sys/stmf_ioctl.h>
42 42 #include <sys/portif.h>
43 43 #define PPPT_TGT_SM_STRINGS
44 44 #include "pppt.h"
45 45
46 46 typedef struct {
47 47 list_node_t te_ctx_node;
48 48 pppt_tgt_event_t te_ctx_event;
49 49 } tgt_event_ctx_t;
50 50
51 51 static void
52 52 pppt_tgt_sm_event(pppt_tgt_t *tgt, pppt_tgt_event_t event);
53 53
54 54 static void
55 55 tgt_sm_event_locked(pppt_tgt_t *tgt, pppt_tgt_event_t event);
56 56
57 57 static void
58 58 tgt_sm_event_dispatch(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
59 59
60 60 static void
61 61 tgt_sm_created(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
62 62
63 63 static void
64 64 tgt_sm_onlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
65 65
66 66 static void
67 67 tgt_sm_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
68 68
69 69 static void
70 70 tgt_sm_stmf_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
71 71
72 72 static void
73 73 tgt_sm_deleting_need_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
74 74
75 75 static void
76 76 tgt_sm_offlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
77 77
78 78 static void
79 79 tgt_sm_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
80 80
81 81 static void
82 82 tgt_sm_stmf_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
83 83
84 84 static void
85 85 tgt_sm_deleting_stmf_dereg(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
86 86
87 87 static void
88 88 tgt_sm_deleting_stmf_dereg_fail(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
89 89
90 90 static void
91 91 tgt_sm_deleting(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx);
92 92
93 93 static void
94 94 pppt_tgt_offline_task(void *arg);
95 95
96 96 static void
97 97 pppt_tgt_dereg_retry(void *arg);
98 98
99 99 static void
100 100 pppt_tgt_dereg_task(void *arg);
101 101
102 102 static void
103 103 tgt_sm_new_state(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx,
104 104 pppt_tgt_state_t new_state);
105 105
106 106 /*ARGSUSED*/
107 107 void
108 108 pppt_tgt_sm_ctl(stmf_local_port_t *lport, int cmd, void *arg)
109 109 {
110 110 pppt_tgt_t *pppt_tgt;
111 111
112 112 pppt_tgt = (pppt_tgt_t *)lport->lport_port_private;
113 113
114 114 switch (cmd) {
115 115 case STMF_CMD_LPORT_ONLINE:
116 116 pppt_tgt_sm_event(pppt_tgt, TE_STMF_ONLINE_REQ);
117 117 break;
118 118 case STMF_CMD_LPORT_OFFLINE:
119 119 pppt_tgt_sm_event(pppt_tgt, TE_STMF_OFFLINE_REQ);
120 120 break;
121 121 case STMF_ACK_LPORT_ONLINE_COMPLETE:
122 122 pppt_tgt_sm_event(pppt_tgt, TE_STMF_ONLINE_COMPLETE_ACK);
123 123 break;
124 124 case STMF_ACK_LPORT_OFFLINE_COMPLETE:
125 125 pppt_tgt_sm_event(pppt_tgt, TE_STMF_OFFLINE_COMPLETE_ACK);
126 126 break;
127 127
128 128 default:
129 129 ASSERT(0);
130 130 break;
131 131 }
132 132 }
133 133
134 134 pppt_tgt_t *
135 135 pppt_tgt_create(stmf_ic_reg_port_msg_t *reg_port, stmf_status_t *msg_errcode)
136 136 {
137 137 pppt_tgt_t *result;
138 138 stmf_local_port_t *lport;
139 139 int total_devid_len;
140 140
141 141 total_devid_len = sizeof (scsi_devid_desc_t) +
142 142 reg_port->icrp_port_id->ident_length - 1;
143 143
144 144 /*
145 145 * Each target is an STMF local port. Allocate an STMF local port
146 146 * including enough space to store a scsi_devid_desc_t for this target.
147 147 */
148 148 lport = stmf_alloc(STMF_STRUCT_STMF_LOCAL_PORT,
149 149 sizeof (pppt_tgt_t) + total_devid_len, 0);
150 150 if (lport == NULL) {
151 151 *msg_errcode = STMF_ALLOC_FAILURE;
152 152 return (NULL);
153 153 }
154 154
155 155 result = lport->lport_port_private;
156 156 result->target_state = TS_CREATED;
157 157 /* Use pointer arithmetic to find scsi_devid_desc_t */
158 158 result->target_devid = (scsi_devid_desc_t *)(result + 1);
159 159 bcopy(reg_port->icrp_port_id, result->target_devid, total_devid_len);
160 160 result->target_devid->piv = 1;
161 161 result->target_devid->code_set = CODE_SET_ASCII;
162 162 result->target_devid->association = ID_IS_TARGET_PORT;
163 163
164 164 mutex_init(&result->target_mutex, NULL, MUTEX_DEFAULT, NULL);
165 165 cv_init(&result->target_cv, NULL, CV_DEFAULT, NULL);
166 166 list_create(&result->target_events, sizeof (tgt_event_ctx_t),
167 167 offsetof(tgt_event_ctx_t, te_ctx_node));
168 168 avl_create(&result->target_sess_list, pppt_sess_avl_compare_by_name,
169 169 sizeof (pppt_sess_t), offsetof(pppt_sess_t, ps_target_ln));
170 170
171 171 lport->lport_abort_timeout = 120; /* seconds */
172 172 lport->lport_id = result->target_devid;
173 173 lport->lport_pp = pppt_global.global_pp;
174 174 lport->lport_ds = pppt_global.global_dbuf_store;
175 175 lport->lport_xfer_data = &pppt_lport_xfer_data;
176 176 lport->lport_send_status = &pppt_lport_send_status;
177 177 lport->lport_task_free = &pppt_lport_task_free;
178 178 lport->lport_abort = &pppt_lport_abort;
179 179 lport->lport_ctl = &pppt_lport_ctl;
180 180 result->target_stmf_lport = lport;
181 181
182 182 /*
183 183 * Since this is a proxy port we need to do set the relative
184 184 * target port identifier before registering it with STMF.
185 185 */
186 186 stmf_set_port_standby(lport, reg_port->icrp_relative_port_id);
187 187
188 188 /*
189 189 * Register the target with STMF. STMF may immediately ask us to go
190 190 * online so insure any additional config setup is complete.
191 191 */
192 192 if (stmf_register_local_port(lport) != STMF_SUCCESS) {
193 193 *msg_errcode = STMF_FAILURE;
194 194 pppt_tgt_destroy(result);
195 195 return (NULL);
196 196 }
197 197
198 198 return (result);
199 199
200 200 }
201 201
202 202 void
203 203 pppt_tgt_destroy(pppt_tgt_t *tgt)
204 204 {
205 205 /* Destroy target */
206 206 avl_destroy(&tgt->target_sess_list);
207 207 list_destroy(&tgt->target_events);
208 208 cv_destroy(&tgt->target_cv);
209 209 mutex_destroy(&tgt->target_mutex);
210 210 stmf_free(tgt->target_stmf_lport); /* Also frees "tgt' */
211 211 }
212 212
213 213 pppt_tgt_t *
214 214 pppt_tgt_lookup(scsi_devid_desc_t *tgt_devid)
215 215 {
216 216 pppt_tgt_t *result;
217 217 PPPT_GLOBAL_LOCK();
218 218 result = pppt_tgt_lookup_locked(tgt_devid);
219 219 PPPT_GLOBAL_UNLOCK();
220 220
221 221 return (result);
222 222 }
223 223
224 224 pppt_tgt_t *
225 225 pppt_tgt_lookup_locked(scsi_devid_desc_t *tgt_devid)
226 226 {
227 227 pppt_tgt_t *result;
228 228 pppt_tgt_t tmptgt;
229 229
230 230 bzero(&tmptgt, sizeof (tmptgt));
231 231 tmptgt.target_devid = tgt_devid;
232 232
233 233 result = avl_find(&pppt_global.global_target_list, &tmptgt, NULL);
234 234
235 235 return (result);
236 236 }
237 237
238 238 void
239 239 pppt_tgt_async_delete(pppt_tgt_t *tgt)
240 240 {
241 241 /* Generate TE_DELETE event to target state machine */
242 242 pppt_tgt_sm_event(tgt, TE_DELETE);
243 243 }
244 244
245 245 int
246 246 pppt_tgt_avl_compare(const void *void_tgt1, const void *void_tgt2)
247 247 {
248 248 const pppt_tgt_t *ptgt1 = void_tgt1;
249 249 const pppt_tgt_t *ptgt2 = void_tgt2;
250 250 int result;
251 251
252 252 /* Sort by code set then ident */
253 253 if (ptgt1->target_devid->code_set <
254 254 ptgt2->target_devid->code_set) {
255 255 return (-1);
256 256 } else if (ptgt1->target_devid->code_set >
257 257 ptgt2->target_devid->code_set) {
258 258 return (1);
259 259 }
260 260
261 261 /* Next by ident length */
262 262 if (ptgt1->target_devid->ident_length <
263 263 ptgt2->target_devid->ident_length) {
264 264 return (-1);
265 265 } else if (ptgt1->target_devid->ident_length >
266 266 ptgt2->target_devid->ident_length) {
267 267 return (1);
268 268 }
269 269
270 270 /* Code set and ident length both match, now compare idents */
271 271 result = memcmp(ptgt1->target_devid->ident, ptgt2->target_devid->ident,
272 272 ptgt1->target_devid->ident_length);
273 273
274 274 if (result < 0) {
275 275 return (-1);
276 276 } else if (result > 0) {
277 277 return (1);
278 278 }
279 279
280 280 return (0);
281 281 }
282 282
283 283 /*
284 284 * Target state machine
285 285 */
286 286
287 287 static void
288 288 pppt_tgt_sm_event(pppt_tgt_t *tgt, pppt_tgt_event_t event)
289 289 {
290 290 mutex_enter(&tgt->target_mutex);
291 291 tgt_sm_event_locked(tgt, event);
292 292 mutex_exit(&tgt->target_mutex);
293 293 }
294 294
295 295 static void
296 296 tgt_sm_event_locked(pppt_tgt_t *tgt, pppt_tgt_event_t event)
297 297 {
298 298 tgt_event_ctx_t *ctx;
299 299
300 300 event = (event < TE_MAX_EVENT) ? event : TE_UNDEFINED;
301 301 DTRACE_PROBE2(pppt__tgt__event, pppt_tgt_t *, tgt,
302 302 pppt_tgt_event_t, event);
303 303 stmf_trace("pppt", "pppt_tgt_event: tgt %p event %s(%d)",
304 304 (void *)tgt, pppt_te_name[event], event);
305 305
306 306 tgt->target_refcount++;
307 307
308 308 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
309 309
310 310 ctx->te_ctx_event = event;
311 311
312 312 list_insert_tail(&tgt->target_events, ctx);
313 313
314 314 /*
315 315 * Use the target_sm_busy flag to keep the state machine single
316 316 * threaded. This also serves as recursion avoidance since this
317 317 * flag will always be set if we call pppt_tgt_sm_event from
318 318 * within the state machine code.
319 319 */
320 320 if (!tgt->target_sm_busy) {
321 321 tgt->target_sm_busy = B_TRUE;
322 322 while (!list_is_empty(&tgt->target_events)) {
323 323 ctx = list_head(&tgt->target_events);
324 324 list_remove(&tgt->target_events, ctx);
325 325 mutex_exit(&tgt->target_mutex);
326 326 tgt_sm_event_dispatch(tgt, ctx);
327 327 mutex_enter(&tgt->target_mutex);
328 328 }
329 329 tgt->target_sm_busy = B_FALSE;
330 330
331 331 }
332 332
333 333 tgt->target_refcount--;
334 334 cv_signal(&tgt->target_cv);
335 335 }
336 336
337 337 static void
338 338 tgt_sm_event_dispatch(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
339 339 {
340 340 stmf_trace("pppt", "pppt_tgt_event_dispatch: tgt %p event %s(%d)",
341 341 (void *)tgt, pppt_te_name[ctx->te_ctx_event], ctx->te_ctx_event);
342 342
343 343 /* State independent actions */
344 344 switch (ctx->te_ctx_event) {
345 345 case TE_DELETE:
346 346 tgt->target_deleting = B_TRUE;
347 347 break;
348 348 }
349 349
350 350 /* State dependent actions */
351 351 switch (tgt->target_state) {
352 352 case TS_CREATED:
353 353 tgt_sm_created(tgt, ctx);
354 354 break;
355 355 case TS_ONLINING:
356 356 tgt_sm_onlining(tgt, ctx);
357 357 break;
358 358 case TS_ONLINE:
359 359 tgt_sm_online(tgt, ctx);
360 360 break;
361 361 case TS_STMF_ONLINE:
362 362 tgt_sm_stmf_online(tgt, ctx);
363 363 break;
364 364 case TS_DELETING_NEED_OFFLINE:
365 365 tgt_sm_deleting_need_offline(tgt, ctx);
366 366 break;
367 367 case TS_OFFLINING:
368 368 tgt_sm_offlining(tgt, ctx);
369 369 break;
370 370 case TS_OFFLINE:
371 371 tgt_sm_offline(tgt, ctx);
372 372 break;
373 373 case TS_STMF_OFFLINE:
374 374 tgt_sm_stmf_offline(tgt, ctx);
375 375 break;
376 376 case TS_DELETING_STMF_DEREG:
377 377 tgt_sm_deleting_stmf_dereg(tgt, ctx);
378 378 break;
379 379 case TS_DELETING_STMF_DEREG_FAIL:
380 380 tgt_sm_deleting_stmf_dereg_fail(tgt, ctx);
381 381 break;
382 382 case TS_DELETING:
383 383 tgt_sm_deleting(tgt, ctx);
384 384 break;
385 385 default:
386 386 ASSERT(0);
387 387 }
388 388
389 389 kmem_free(ctx, sizeof (*ctx));
390 390 }
391 391
392 392 static void
393 393 tgt_sm_created(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
394 394 {
395 395 stmf_change_status_t scs;
396 396
397 397 switch (ctx->te_ctx_event) {
398 398 case TE_STMF_ONLINE_REQ:
399 399 tgt_sm_new_state(tgt, ctx, TS_ONLINING);
400 400 break;
401 401 case TE_DELETE:
402 402 tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG);
403 403 break;
404 404 case TE_STMF_OFFLINE_REQ:
405 405 /*
406 406 * We're already offline but update to an equivelant
407 407 * state just to note that STMF talked to us.
408 408 */
409 409 scs.st_completion_status = STMF_SUCCESS;
410 410 scs.st_additional_info = NULL;
411 411 tgt_sm_new_state(tgt, ctx, TS_OFFLINE);
412 412 (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE,
413 413 tgt->target_stmf_lport, &scs);
414 414 break;
415 415 case TE_STMF_ONLINE_COMPLETE_ACK:
416 416 case TE_STMF_OFFLINE_COMPLETE_ACK:
417 417 /* Ignore */
418 418 break;
419 419 default:
420 420 ASSERT(0);
421 421 }
422 422 }
423 423
424 424 static void
425 425 tgt_sm_onlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
426 426 {
427 427 stmf_change_status_t scs;
428 428
429 429 switch (ctx->te_ctx_event) {
430 430 case TE_ONLINE_SUCCESS:
431 431 tgt_sm_new_state(tgt, ctx, TS_ONLINE);
432 432 break;
433 433 case TE_ONLINE_FAIL:
434 434 tgt_sm_new_state(tgt, ctx, TS_STMF_OFFLINE);
435 435 break;
436 436 case TE_DELETE:
437 437 /* TE_DELETE is handled in tgt_sm_event_dispatch() */
438 438 break;
439 439 case TE_STMF_ONLINE_REQ:
440 440 case TE_STMF_OFFLINE_REQ:
441 441 /*
442 442 * We can't complete STMF's request since we are busy going
443 443 * online.
444 444 */
445 445 scs.st_completion_status = STMF_INVALID_ARG;
446 446 scs.st_additional_info = NULL;
447 447 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
448 448 STMF_CMD_LPORT_ONLINE_COMPLETE :
449 449 STMF_CMD_LPORT_OFFLINE_COMPLETE,
450 450 tgt->target_stmf_lport, &scs);
451 451 break;
452 452 case TE_STMF_ONLINE_COMPLETE_ACK:
453 453 case TE_STMF_OFFLINE_COMPLETE_ACK:
454 454 /* Ignore */
455 455 break;
456 456 default:
457 457 ASSERT(0);
458 458 }
459 459 }
460 460
461 461 static void
462 462 tgt_sm_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
463 463 {
464 464 stmf_change_status_t scs;
465 465
466 466 switch (ctx->te_ctx_event) {
467 467 case TE_STMF_ONLINE_COMPLETE_ACK:
468 468 if (tgt->target_deleting) {
469 469 tgt_sm_new_state(tgt, ctx, TS_DELETING_NEED_OFFLINE);
470 470 } else {
471 471 tgt_sm_new_state(tgt, ctx, TS_STMF_ONLINE);
472 472 }
473 473 break;
474 474 case TE_DELETE:
475 475 /* TE_DELETE is handled in tgt_sm_event_dispatch() */
476 476 break;
477 477 case TE_STMF_ONLINE_REQ:
478 478 case TE_STMF_OFFLINE_REQ:
479 479 /*
480 480 * We can't complete STMF's request since we are busy going
481 481 * online (waiting for acknowlegement from STMF)
482 482 */
483 483 scs.st_completion_status = STMF_INVALID_ARG;
484 484 scs.st_additional_info = NULL;
485 485 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
486 486 STMF_CMD_LPORT_ONLINE_COMPLETE :
487 487 STMF_CMD_LPORT_OFFLINE_COMPLETE,
488 488 tgt->target_stmf_lport, &scs);
489 489 break;
490 490 case TE_STMF_OFFLINE_COMPLETE_ACK:
491 491 /* Ignore */
492 492 break;
493 493 default:
494 494 ASSERT(0);
495 495 }
496 496 }
497 497
498 498
499 499 static void
500 500 tgt_sm_stmf_online(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
501 501 {
502 502 stmf_change_status_t scs;
503 503
504 504 switch (ctx->te_ctx_event) {
505 505 case TE_DELETE:
506 506 tgt_sm_new_state(tgt, ctx, TS_DELETING_NEED_OFFLINE);
507 507 break;
508 508 case TE_STMF_OFFLINE_REQ:
509 509 tgt_sm_new_state(tgt, ctx, TS_OFFLINING);
510 510 break;
511 511 case TE_STMF_ONLINE_REQ:
512 512 /* Already online */
513 513 scs.st_completion_status = STMF_ALREADY;
514 514 scs.st_additional_info = NULL;
515 515 (void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE,
516 516 tgt->target_stmf_lport, &scs);
517 517 break;
518 518 case TE_STMF_ONLINE_COMPLETE_ACK:
519 519 case TE_STMF_OFFLINE_COMPLETE_ACK:
520 520 /* Ignore */
521 521 break;
522 522 default:
523 523 ASSERT(0);
524 524 }
525 525 }
526 526
527 527
528 528 static void
529 529 tgt_sm_deleting_need_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
530 530 {
531 531 stmf_change_status_t scs;
532 532
533 533 switch (ctx->te_ctx_event) {
534 534 case TE_STMF_OFFLINE_REQ:
535 535 tgt_sm_new_state(tgt, ctx, TS_OFFLINING);
536 536 break;
537 537 case TE_DELETE:
538 538 /* TE_DELETE is handled in tgt_sm_event_dispatch() */
539 539 break;
540 540 case TE_STMF_ONLINE_REQ:
541 541 /*
542 542 * We can't complete STMF's request since we need to be offlined
543 543 */
544 544 scs.st_completion_status = STMF_INVALID_ARG;
545 545 scs.st_additional_info = NULL;
546 546 (void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE,
547 547 tgt->target_stmf_lport, &scs);
548 548 break;
549 549 case TE_STMF_ONLINE_COMPLETE_ACK:
550 550 case TE_STMF_OFFLINE_COMPLETE_ACK:
551 551 /* Ignore */
552 552 break;
553 553 default:
554 554 ASSERT(0);
555 555 }
556 556 }
557 557
558 558
559 559 static void
560 560 tgt_sm_offlining(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
561 561 {
562 562 stmf_change_status_t scs;
563 563
564 564 switch (ctx->te_ctx_event) {
565 565 case TE_OFFLINE_COMPLETE:
566 566 tgt_sm_new_state(tgt, ctx, TS_OFFLINE);
567 567 break;
568 568 case TE_DELETE:
569 569 /* TE_DELETE is handled in tgt_sm_event_dispatch() */
570 570 break;
571 571 case TE_STMF_ONLINE_REQ:
572 572 case TE_STMF_OFFLINE_REQ:
573 573 /*
574 574 * We can't complete STMF's request since we are busy going
575 575 * offline.
576 576 */
577 577 scs.st_completion_status = STMF_INVALID_ARG;
578 578 scs.st_additional_info = NULL;
579 579 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
580 580 STMF_CMD_LPORT_ONLINE_COMPLETE :
581 581 STMF_CMD_LPORT_OFFLINE_COMPLETE,
582 582 tgt->target_stmf_lport, &scs);
583 583 break;
584 584 case TE_STMF_ONLINE_COMPLETE_ACK:
585 585 case TE_STMF_OFFLINE_COMPLETE_ACK:
586 586 /* Ignore */
587 587 break;
588 588 default:
589 589 ASSERT(0);
590 590 }
591 591 }
592 592
593 593
594 594 static void
595 595 tgt_sm_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
596 596 {
597 597 stmf_change_status_t scs;
598 598
599 599 switch (ctx->te_ctx_event) {
600 600 case TE_STMF_OFFLINE_COMPLETE_ACK:
601 601 if (tgt->target_deleting) {
602 602 tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG);
603 603 } else {
604 604 tgt_sm_new_state(tgt, ctx, TS_STMF_OFFLINE);
605 605 }
606 606 break;
607 607 case TE_DELETE:
608 608 /* TE_DELETE is handled in tgt_sm_event_dispatch() */
609 609 break;
610 610 case TE_STMF_ONLINE_REQ:
611 611 case TE_STMF_OFFLINE_REQ:
612 612 /*
613 613 * We can't complete STMF's request since we are busy going
614 614 * offline.
615 615 */
616 616 scs.st_completion_status = STMF_INVALID_ARG;
617 617 scs.st_additional_info = NULL;
618 618 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
619 619 STMF_CMD_LPORT_ONLINE_COMPLETE :
620 620 STMF_CMD_LPORT_OFFLINE_COMPLETE,
621 621 tgt->target_stmf_lport, &scs);
622 622 break;
623 623 case TE_STMF_ONLINE_COMPLETE_ACK:
624 624 /* Ignore */
625 625 break;
626 626 default:
627 627 ASSERT(0);
628 628 }
629 629 }
630 630
631 631
632 632 static void
633 633 tgt_sm_stmf_offline(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
634 634 {
635 635 stmf_change_status_t scs;
636 636
637 637 switch (ctx->te_ctx_event) {
638 638 case TE_STMF_ONLINE_REQ:
639 639 tgt_sm_new_state(tgt, ctx, TS_ONLINING);
640 640 break;
641 641 case TE_DELETE:
642 642 tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG);
643 643 break;
644 644 case TE_STMF_OFFLINE_REQ:
645 645 /* Already offline */
646 646 scs.st_completion_status = STMF_ALREADY;
647 647 scs.st_additional_info = NULL;
648 648 (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE,
649 649 tgt->target_stmf_lport, &scs);
650 650 break;
651 651 case TE_STMF_ONLINE_COMPLETE_ACK:
652 652 case TE_STMF_OFFLINE_COMPLETE_ACK:
653 653 /* Ignore */
654 654 break;
655 655 default:
656 656 ASSERT(0);
657 657 }
658 658 }
659 659
660 660
661 661 static void
662 662 tgt_sm_deleting_stmf_dereg(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
663 663 {
664 664 stmf_change_status_t scs;
665 665
666 666 /* Terminal state, no events */
667 667 switch (ctx->te_ctx_event) {
668 668 case TE_STMF_ONLINE_REQ:
669 669 case TE_STMF_OFFLINE_REQ:
670 670 /*
671 671 * We can't complete STMF's request since we are being deleted
672 672 */
673 673 scs.st_completion_status = STMF_INVALID_ARG;
674 674 scs.st_additional_info = NULL;
675 675 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
676 676 STMF_CMD_LPORT_ONLINE_COMPLETE :
677 677 STMF_CMD_LPORT_OFFLINE_COMPLETE,
678 678 tgt->target_stmf_lport, &scs);
679 679 break;
680 680 case TE_STMF_ONLINE_COMPLETE_ACK:
681 681 case TE_STMF_OFFLINE_COMPLETE_ACK:
682 682 /* Ignore */
683 683 break;
684 684 case TE_STMF_DEREG_SUCCESS:
685 685 tgt_sm_new_state(tgt, ctx, TS_DELETING);
686 686 break;
687 687 case TE_STMF_DEREG_FAIL:
688 688 tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG_FAIL);
689 689 break;
690 690 default:
691 691 ASSERT(0);
692 692 }
693 693 }
694 694
695 695 static void
696 696 tgt_sm_deleting_stmf_dereg_fail(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
697 697 {
698 698 stmf_change_status_t scs;
699 699
700 700 /* Terminal state, no events */
701 701 switch (ctx->te_ctx_event) {
702 702 case TE_STMF_ONLINE_REQ:
703 703 case TE_STMF_OFFLINE_REQ:
704 704 /*
705 705 * We can't complete STMF's request since we are being deleted
706 706 */
707 707 scs.st_completion_status = STMF_INVALID_ARG;
708 708 scs.st_additional_info = NULL;
709 709 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
710 710 STMF_CMD_LPORT_ONLINE_COMPLETE :
711 711 STMF_CMD_LPORT_OFFLINE_COMPLETE,
712 712 tgt->target_stmf_lport, &scs);
713 713 break;
714 714 case TE_STMF_ONLINE_COMPLETE_ACK:
715 715 case TE_STMF_OFFLINE_COMPLETE_ACK:
716 716 /* Ignore */
717 717 break;
718 718 case TE_STMF_DEREG_RETRY:
719 719 tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG);
720 720 break;
721 721 default:
722 722 ASSERT(0);
723 723 }
724 724 }
725 725
726 726 static void
727 727 tgt_sm_deleting(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx)
728 728 {
729 729 stmf_change_status_t scs;
730 730
731 731 /* Terminal state, no events */
732 732 switch (ctx->te_ctx_event) {
733 733 case TE_STMF_ONLINE_REQ:
734 734 case TE_STMF_OFFLINE_REQ:
735 735 /*
736 736 * We can't complete STMF's request since we are being deleted
737 737 */
738 738 scs.st_completion_status = STMF_INVALID_ARG;
739 739 scs.st_additional_info = NULL;
740 740 (void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
741 741 STMF_CMD_LPORT_ONLINE_COMPLETE :
742 742 STMF_CMD_LPORT_OFFLINE_COMPLETE,
743 743 tgt->target_stmf_lport, &scs);
744 744 break;
745 745 case TE_STMF_ONLINE_COMPLETE_ACK:
746 746 case TE_STMF_OFFLINE_COMPLETE_ACK:
747 747 /* Ignore */
748 748 break;
749 749 default:
750 750 ASSERT(0);
751 751 }
752 752 }
753 753
754 754 static void
755 755 pppt_tgt_offline(pppt_tgt_t *tgt)
756 756 {
757 757 (void) taskq_dispatch(pppt_global.global_dispatch_taskq,
758 758 pppt_tgt_offline_task, tgt, KM_SLEEP);
759 759 }
760 760
761 761 static void
762 762 pppt_tgt_offline_task(void *arg)
763 763 {
764 764 pppt_tgt_t *tgt = arg;
765 765 pppt_sess_t *ps, *next_ps;
766 766 stmf_change_status_t scs;
767 767
768 768 stmf_trace("pppt", "pppt_tgt_offline %p", (void *)tgt);
769 769
770 770 PPPT_GLOBAL_LOCK();
771 771 mutex_enter(&tgt->target_mutex);
772 772 for (ps = avl_first(&tgt->target_sess_list); ps != NULL; ps = next_ps) {
773 773 next_ps = AVL_NEXT(&tgt->target_sess_list, ps);
774 774 mutex_enter(&ps->ps_mutex);
775 775 if (!ps->ps_closed) {
776 776 pppt_sess_close_locked(ps);
777 777 }
778 778 mutex_exit(&ps->ps_mutex);
779 779 }
780 780 mutex_exit(&tgt->target_mutex);
781 781 PPPT_GLOBAL_UNLOCK();
782 782
783 783 pppt_tgt_sm_event(tgt, TE_OFFLINE_COMPLETE);
784 784
785 785 scs.st_completion_status = STMF_SUCCESS;
786 786 scs.st_additional_info = NULL;
787 787 (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE,
788 788 tgt->target_stmf_lport, &scs);
789 789
790 790 stmf_trace("pppt", "pppt_tgt_offline complete %p", (void *)tgt);
791 791 }
792 792
793 793 static void
794 794 pppt_tgt_dereg_retry(void *arg)
795 795 {
796 796 pppt_tgt_t *tgt = arg;
797 797
↓ open down ↓ |
797 lines elided |
↑ open up ↑ |
798 798 /*
799 799 * Rather than guaranteeing the target state machine code will not
800 800 * block for long periods of time (tying up this callout thread)
801 801 * we will queue a task on the taskq to send the retry event.
802 802 * If it fails we'll setup another timeout and try again later.
803 803 */
804 804 if (taskq_dispatch(pppt_global.global_dispatch_taskq,
805 805 pppt_tgt_dereg_task, tgt, KM_NOSLEEP) == NULL) {
806 806 /* Dispatch failed, try again later */
807 807 (void) timeout(pppt_tgt_dereg_retry, tgt,
808 - drv_usectohz(TGT_DEREG_RETRY_SECONDS * 1000000));
808 + drv_sectohz(TGT_DEREG_RETRY_SECONDS));
809 809 }
810 810 }
811 811
812 812 static void
813 813 pppt_tgt_dereg_task(void *arg)
814 814 {
815 815 pppt_tgt_t *tgt = arg;
816 816
817 817 pppt_tgt_sm_event(tgt, TE_STMF_DEREG_RETRY);
818 818 }
819 819
820 820 /*ARGSUSED*/
821 821 static void
822 822 tgt_sm_new_state(pppt_tgt_t *tgt, tgt_event_ctx_t *ctx,
823 823 pppt_tgt_state_t new_state)
824 824 {
825 825 stmf_local_port_t *lport = tgt->target_stmf_lport;
826 826 stmf_change_status_t scs;
827 827 stmf_state_change_info_t sci;
828 828 stmf_status_t stmfrc;
829 829
830 830 scs.st_completion_status = STMF_SUCCESS;
831 831 scs.st_additional_info = NULL;
832 832
833 833 /*
834 834 * Validate new state
835 835 */
836 836 ASSERT(new_state != TS_UNDEFINED);
837 837 ASSERT3U(new_state, <, TS_MAX_STATE);
838 838
839 839 new_state = (new_state < TS_MAX_STATE) ?
840 840 new_state : TS_UNDEFINED;
841 841
842 842 stmf_trace("pppt", "pppt_target_state_change: "
843 843 "tgt %p, %s(%d) --> %s(%d)\n",
844 844 (void *) tgt, pppt_ts_name[tgt->target_state], tgt->target_state,
845 845 pppt_ts_name[new_state], new_state);
846 846 DTRACE_PROBE3(pppt__target__state__change,
847 847 pppt_tgt_t *, tgt, tgt_event_ctx_t *, ctx,
848 848 pppt_tgt_state_t, new_state);
849 849
850 850 mutex_enter(&tgt->target_mutex);
851 851 tgt->target_last_state = tgt->target_state;
852 852 tgt->target_state = new_state;
853 853 cv_signal(&tgt->target_cv);
854 854 mutex_exit(&tgt->target_mutex);
855 855
856 856 switch (tgt->target_state) {
857 857 case TS_ONLINING:
858 858 pppt_tgt_sm_event(tgt, TE_ONLINE_SUCCESS);
859 859
860 860 /*
861 861 * Let STMF know the how the online operation completed.
862 862 * STMF will respond with an acknowlege later
863 863 */
864 864 (void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE, lport, &scs);
865 865 break;
866 866 case TS_ONLINE:
867 867 break;
868 868 case TS_STMF_ONLINE:
869 869 break;
870 870 case TS_DELETING_NEED_OFFLINE:
871 871 sci.st_rflags = STMF_RFLAG_STAY_OFFLINED;
872 872 sci.st_additional_info = "Offline for delete";
873 873 (void) stmf_ctl(STMF_CMD_LPORT_OFFLINE, lport, &sci);
874 874 break;
875 875 case TS_OFFLINING:
876 876 /* Async callback generates completion event */
877 877 pppt_tgt_offline(tgt);
878 878 break;
879 879 case TS_OFFLINE:
880 880 break;
881 881 case TS_STMF_OFFLINE:
882 882 break;
883 883 case TS_DELETING_STMF_DEREG:
884 884 stmfrc = stmf_deregister_local_port(tgt->target_stmf_lport);
885 885 if (stmfrc == STMF_SUCCESS) {
886 886 pppt_tgt_sm_event(tgt, TE_STMF_DEREG_SUCCESS);
887 887 } else {
888 888 pppt_tgt_sm_event(tgt, TE_STMF_DEREG_FAIL);
889 889 }
890 890 break;
891 891 case TS_DELETING_STMF_DEREG_FAIL:
892 892 /* Retry dereg in 1 second */
893 893 (void) timeout(pppt_tgt_dereg_retry, tgt,
894 894 drv_usectohz(TGT_DEREG_RETRY_SECONDS * 1000000));
895 895 break;
896 896 case TS_DELETING:
897 897 break;
898 898 default:
899 899 ASSERT(0);
900 900 }
901 901 }
↓ open down ↓ |
83 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX