4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 #include <sys/param.h>
30 #include <sys/errno.h>
34 #include <sys/modctl.h>
36 #include <sys/stream.h>
37 #include <sys/strsubr.h>
38 #include <sys/strsun.h>
40 #include <sys/sunddi.h>
42 #include <sys/sbp2/impl.h>
43 #include <sys/1394/ieee1212.h>
46 static void sbp2_tgt_init_sobj(sbp2_tgt_t
*);
47 static void sbp2_tgt_fini_sobj(sbp2_tgt_t
*);
48 static int sbp2_tgt_init_params(sbp2_tgt_t
*);
49 static int sbp2_tgt_init_luns(sbp2_tgt_t
*, int);
50 static void sbp2_tgt_fini_luns(sbp2_tgt_t
*);
51 static int sbp2_tgt_init_bus(sbp2_tgt_t
*);
52 static void sbp2_tgt_fini_bus(sbp2_tgt_t
*);
53 static int sbp2_tgt_mgt_request(sbp2_tgt_t
*, int *);
54 static int sbp2_tgt_task_mgt_request(sbp2_tgt_t
*, uint16_t, int, uint64_t,
58 static void sbp2_lun_logout_orb(sbp2_lun_t
*, sbp2_tgt_t
*, int *);
59 static boolean_t
sbp2_lun_accepting_tasks(sbp2_lun_t
*);
61 /* session routines */
62 static int sbp2_ses_init(sbp2_ses_t
**, sbp2_lun_t
*,
63 void (*)(void *, sbp2_task_t
*), void *);
64 static void sbp2_ses_fini(sbp2_ses_t
*);
65 static sbp2_task_t
*sbp2_ses_orbp2task(sbp2_ses_t
*, uint64_t);
66 static void sbp2_ses_append_task(sbp2_ses_t
*, sbp2_task_t
*);
67 static void sbp2_ses_reset_pending_tasks(sbp2_ses_t
*, uint16_t);
68 static int sbp2_ses_reconnect_orb(sbp2_ses_t
*, int *);
70 /* orb alloc routines */
71 static sbp2_bus_buf_t
*sbp2_orb_freelist_get(sbp2_lun_t
*, sbp2_task_t
*, int);
72 static int sbp2_orb_freelist_put(sbp2_lun_t
*, sbp2_bus_buf_t
*);
73 static void sbp2_orb_freelist_destroy(sbp2_lun_t
*);
75 /* fetch agent routines */
76 static int sbp2_agent_init(sbp2_agent_t
*, uint64_t, sbp2_tgt_t
*tp
);
77 static void sbp2_agent_fini(sbp2_agent_t
*);
78 static void sbp2_agent_acquire_locked(sbp2_agent_t
*);
79 static void sbp2_agent_release_locked(sbp2_agent_t
*);
80 static void sbp2_agent_acquire(sbp2_agent_t
*);
81 static void sbp2_agent_release(sbp2_agent_t
*);
82 static int sbp2_agent_keepalive(sbp2_agent_t
*, int *);
83 static int sbp2_agent_doorbell(sbp2_agent_t
*, int *);
84 static int sbp2_agent_write_orbp(sbp2_agent_t
*, uint64_t, int *);
85 static int sbp2_agent_reset(sbp2_agent_t
*, int *);
87 /* callbacks and timeouts */
88 static void sbp2_mgt_status_fifo_wb_cb(sbp2_bus_buf_t
*, void *, mblk_t
**);
89 static void sbp2_task_timeout(void *);
90 static void sbp2_status_fifo_wb_cb(sbp2_bus_buf_t
*, void *, mblk_t
**);
93 static void sbp2_mgt_agent_acquire(sbp2_tgt_t
*);
94 static void sbp2_mgt_agent_release(sbp2_tgt_t
*);
95 static void sbp2_fetch_agent_acquire(sbp2_ses_t
*);
96 static void sbp2_fetch_agent_release(sbp2_ses_t
*);
98 extern struct mod_ops mod_miscops
;
100 static struct modlmisc sbp2_modlmisc
= {
101 &mod_miscops
, /* module type */
102 "Serial Bus Protocol 2 module" /* module name */
105 static struct modlinkage sbp2_modlinkage
= {
106 MODREV_1
, (void *)&sbp2_modlmisc
, NULL
110 int sbp2_submit_reset_nretries
= 3;
111 clock_t sbp2_submit_reset_delay
= 10; /* microsec */
113 int sbp2_write_orbp_nretries
= 3;
114 clock_t sbp2_write_orbp_delay
= 10; /* microsec */
116 _NOTE(SCHEME_PROTECTS_DATA("unique per call", datab msgb
))
120 * --- loadable module entry points
126 return (mod_install(&sbp2_modlinkage
));
133 return (mod_remove(&sbp2_modlinkage
));
138 _info(struct modinfo
*modinfop
)
140 return (mod_info(&sbp2_modlinkage
, modinfop
));
145 * --- target routines
149 sbp2_tgt_init(void *bus_hdl
, sbp2_bus_t
*bus
, int maxluns
, sbp2_tgt_t
**tpp
)
154 tp
= kmem_zalloc(sizeof (sbp2_tgt_t
), KM_SLEEP
);
156 tp
->t_bus_hdl
= bus_hdl
;
158 sbp2_tgt_init_sobj(tp
);
160 if ((ret
= sbp2_cfgrom_parse(tp
, &tp
->t_cfgrom
)) != SBP2_SUCCESS
) {
161 sbp2_tgt_fini_sobj(tp
);
162 kmem_free(tp
, sizeof (sbp2_tgt_t
));
163 return (SBP2_ECFGROM
);
166 if ((ret
= sbp2_tgt_init_params(tp
)) != SBP2_SUCCESS
) {
167 sbp2_cfgrom_free(tp
, &tp
->t_cfgrom
);
168 sbp2_tgt_fini_sobj(tp
);
169 kmem_free(tp
, sizeof (sbp2_tgt_t
));
173 if ((ret
= sbp2_tgt_init_luns(tp
, maxluns
)) != SBP2_SUCCESS
) {
174 sbp2_cfgrom_free(tp
, &tp
->t_cfgrom
);
175 sbp2_tgt_fini_sobj(tp
);
176 kmem_free(tp
, sizeof (sbp2_tgt_t
));
180 if ((ret
= sbp2_tgt_init_bus(tp
)) != SBP2_SUCCESS
) {
181 sbp2_tgt_fini_luns(tp
);
182 sbp2_cfgrom_free(tp
, &tp
->t_cfgrom
);
183 sbp2_tgt_fini_sobj(tp
);
184 kmem_free(tp
, sizeof (sbp2_tgt_t
));
189 return (SBP2_SUCCESS
);
193 sbp2_tgt_fini(sbp2_tgt_t
*tp
)
195 sbp2_tgt_fini_bus(tp
);
196 sbp2_tgt_fini_luns(tp
);
197 sbp2_cfgrom_free(tp
, &tp
->t_cfgrom
);
198 sbp2_tgt_fini_sobj(tp
);
199 kmem_free(tp
, sizeof (sbp2_tgt_t
));
203 sbp2_tgt_init_sobj(sbp2_tgt_t
*tp
)
205 mutex_init(&tp
->t_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
206 cv_init(&tp
->t_mgt_agent_cv
, NULL
, CV_DRIVER
, NULL
);
207 cv_init(&tp
->t_mgt_status_cv
, NULL
, CV_DRIVER
, NULL
);
211 sbp2_tgt_fini_sobj(sbp2_tgt_t
*tp
)
213 cv_destroy(&tp
->t_mgt_status_cv
);
214 cv_destroy(&tp
->t_mgt_agent_cv
);
215 mutex_destroy(&tp
->t_mutex
);
219 sbp2_tgt_init_params(sbp2_tgt_t
*tp
)
221 sbp2_cfgrom_ent_t
*root
= &tp
->t_cfgrom
.cr_root
;
222 sbp2_cfgrom_ent_t
*ent
;
225 /* MANAGEMENT_AGENT */
226 if ((ent
= sbp2_cfgrom_ent_by_key(root
, SBP2_KT_MGT_AGENT
,
227 SBP2_KV_MGT_AGENT
, 0)) == NULL
) {
228 return (SBP2_ECFGROM
);
230 tp
->t_mgt_agent
= SBP2_CSR_BASE(tp
) + ent
->ce_data
.offset
* 4;
232 /* Unit_Characteristics */
233 if ((ent
= sbp2_cfgrom_ent_by_key(root
, SBP2_KT_UNCHAR
,
234 SBP2_KV_UNCHAR
, 0)) == NULL
) {
235 return (SBP2_ECFGROM
);
237 q
= ent
->ce_data
.imm
;
239 /* units of 500 ms -> ms */
240 tp
->t_mot
= ((q
& SBP2_UNCHAR_MOT
) >> SBP2_UNCHAR_MOT_SHIFT
) * 500;
242 /* quadlets -> bytes */
243 tp
->t_orb_size
= (q
& SBP2_UNCHAR_ORB_SIZE
) * 4;
245 /* some devices return incorrect values */
246 if (tp
->t_mot
< SBP2_MOT_MIN
) {
247 tp
->t_mot
= SBP2_MOT_DFLT
;
249 if (tp
->t_orb_size
< SBP2_ORB_SIZE_MIN
) {
250 tp
->t_orb_size
= SBP2_ORB_SIZE_MIN
;
253 return (SBP2_SUCCESS
);
259 sbp2_tgt_init_luns(sbp2_tgt_t
*tp
, int maxluns
)
261 sbp2_cfgrom_ent_t
*root
= &tp
->t_cfgrom
.cr_root
;
262 sbp2_cfgrom_ent_t
*ent
;
266 ASSERT(tp
->t_nluns
== 0);
268 tp
->t_lun
= kmem_zalloc(maxluns
* sizeof (sbp2_lun_t
), KM_SLEEP
);
269 tp
->t_nluns_alloc
= maxluns
;
271 /* search for Logical_Unit_Number's */
272 for (tp
->t_nluns
= 0; tp
->t_nluns
< maxluns
; tp
->t_nluns
++) {
273 if ((ent
= sbp2_cfgrom_ent_by_key(root
, SBP2_KT_LUN
,
274 SBP2_KV_LUN
, tp
->t_nluns
)) == NULL
) {
277 q
= ent
->ce_data
.imm
;
278 lp
= &tp
->t_lun
[tp
->t_nluns
];
280 lp
->l_lun
= q
& SBP2_LUN_NUM
;
281 lp
->l_type
= (q
& SBP2_LUN_TYPE
) >> SBP2_LUN_TYPE_SHIFT
;
282 mutex_init(&lp
->l_orb_freelist
.bl_mutex
, NULL
, MUTEX_DRIVER
,
286 if (tp
->t_nluns
> 0) {
287 return (SBP2_SUCCESS
);
289 kmem_free(tp
->t_lun
, tp
->t_nluns_alloc
* sizeof (sbp2_lun_t
));
290 return (SBP2_ECFGROM
);
297 sbp2_tgt_fini_luns(sbp2_tgt_t
*tp
)
302 /* destroy each lun */
303 for (i
= 0; i
< tp
->t_nluns
; i
++) {
305 sbp2_orb_freelist_destroy(lp
);
306 mutex_destroy(&lp
->l_orb_freelist
.bl_mutex
);
309 kmem_free(tp
->t_lun
, tp
->t_nluns_alloc
* sizeof (sbp2_lun_t
));
313 * initialize bus buffers and commands
316 sbp2_tgt_init_bus(sbp2_tgt_t
*tp
)
321 * We serialize management requests and reuse the same buffers.
325 tp
->t_mgt_orb_buf
.bb_len
=
326 SBP2_ORB_SIZE_ROUNDUP(tp
, sizeof (sbp2_mgt_orb_t
));
327 tp
->t_mgt_orb_buf
.bb_flags
= SBP2_BUS_BUF_DMA
| SBP2_BUS_BUF_RD
;
328 if ((ret
= SBP2_ALLOC_BUF(tp
, &tp
->t_mgt_orb_buf
)) != SBP2_SUCCESS
) {
329 sbp2_tgt_fini_bus(tp
);
336 tp
->t_mgt_status_fifo_buf
.bb_len
= sizeof (sbp2_status_t
);
337 tp
->t_mgt_status_fifo_buf
.bb_flags
= SBP2_BUS_BUF_WR_POSTED
;
338 tp
->t_mgt_status_fifo_buf
.bb_wb_cb
= sbp2_mgt_status_fifo_wb_cb
;
339 tp
->t_mgt_status_fifo_buf
.bb_sbp2_priv
= tp
;
340 if ((ret
= SBP2_ALLOC_BUF(tp
, &tp
->t_mgt_status_fifo_buf
)) !=
348 tp
->t_mgt_login_resp_buf
.bb_len
=
349 SBP2_ORB_SIZE_ROUNDUP(tp
, sizeof (sbp2_login_resp_t
));
351 * read-only should have been sufficient here, but it causes
352 * DVMA errors on Grover, while read/write works just fine
354 tp
->t_mgt_login_resp_buf
.bb_flags
= SBP2_BUS_BUF_DMA
| SBP2_BUS_BUF_RW
;
355 if ((ret
= SBP2_ALLOC_BUF(tp
, &tp
->t_mgt_login_resp_buf
)) !=
357 sbp2_tgt_fini_bus(tp
);
362 * allocate bus commands
364 if ((ret
= SBP2_ALLOC_CMD(tp
, &tp
->t_mgt_cmd
, 0)) != SBP2_SUCCESS
) {
365 sbp2_tgt_fini_bus(tp
);
368 if ((tp
->t_mgt_cmd_data
= allocb(8, BPRI_HI
)) == NULL
) {
369 sbp2_tgt_fini_bus(tp
);
370 return (SBP2_ENOMEM
);
373 return (SBP2_SUCCESS
);
377 sbp2_tgt_fini_bus(sbp2_tgt_t
*tp
)
379 if (tp
->t_mgt_status_fifo_buf
.bb_hdl
!= NULL
) {
380 SBP2_FREE_BUF(tp
, &tp
->t_mgt_status_fifo_buf
);
382 if (tp
->t_mgt_orb_buf
.bb_hdl
!= NULL
) {
383 SBP2_FREE_BUF(tp
, &tp
->t_mgt_orb_buf
);
385 if (tp
->t_mgt_login_resp_buf
.bb_hdl
!= NULL
) {
386 SBP2_FREE_BUF(tp
, &tp
->t_mgt_login_resp_buf
);
389 SBP2_FREE_CMD(tp
, tp
->t_mgt_cmd
);
390 tp
->t_mgt_cmd
= NULL
;
392 if (tp
->t_mgt_cmd_data
) {
393 freeb(tp
->t_mgt_cmd_data
);
394 tp
->t_mgt_cmd_data
= NULL
;
399 sbp2_tgt_disconnect(sbp2_tgt_t
*tp
)
401 sbp2_tgt_fini_bus(tp
);
405 sbp2_tgt_reconnect(sbp2_tgt_t
*tp
)
407 return (sbp2_tgt_init_bus(tp
));
411 * send mgt ORB and wait for status
413 * mgt agent should be acquired
416 sbp2_tgt_mgt_request(sbp2_tgt_t
*tp
, int *berr
)
422 * When a ctl operation happens from HAL - this could be 0!
423 * This will happen when a device is disconected and then
424 * reconnected. Note there are problems with not being able
425 * to detach/eject a target before unplugging. That can cause
426 * this to happen... This problem needs some work elseware!
427 * This just prevents a needless panic. If we return failure
428 * the target ultimatly will recover and is usable.
430 if (tp
->t_mgt_cmd_data
== 0) {
431 return (SBP2_FAILURE
);
434 tp
->t_mgt_status_rcvd
= B_FALSE
;
436 /* write ORB address into MANAGEMENT_AGENT */
437 SBP2_ADDR_SET(tp
->t_mgt_cmd_data
->b_rptr
, tp
->t_mgt_orb_buf
.bb_baddr
,
439 tp
->t_mgt_cmd_data
->b_wptr
= tp
->t_mgt_cmd_data
->b_rptr
+ 8;
441 if ((ret
= SBP2_WB(tp
, tp
->t_mgt_cmd
, tp
->t_mgt_agent
,
442 tp
->t_mgt_cmd_data
, 8, berr
)) != SBP2_SUCCESS
) {
446 /* wait for login response */
447 mutex_enter(&tp
->t_mutex
);
448 until
= ddi_get_lbolt() + drv_usectohz(tp
->t_mot
* 1000);
451 while (!tp
->t_mgt_status_rcvd
&& (ret
> 0)) {
452 ret
= cv_timedwait(&tp
->t_mgt_status_cv
, &tp
->t_mutex
, until
);
455 if (!tp
->t_mgt_status_rcvd
) {
457 } else if ((tp
->t_mgt_status
.st_param
& SBP2_ST_RESP
) ==
458 SBP2_ST_RESP_COMPLETE
) {
463 mutex_exit(&tp
->t_mutex
);
469 * Send task management request, one of:
471 * ABORT TASK, ABORT TASK SET, LOGICAL UNIT RESET, TARGET RESET
474 sbp2_tgt_task_mgt_request(sbp2_tgt_t
*tp
, uint16_t id
, int func
, uint64_t orbp
,
477 sbp2_task_mgt_orb_t
*torb
;
480 sbp2_mgt_agent_acquire(tp
);
482 torb
= (sbp2_task_mgt_orb_t
*)tp
->t_mgt_orb_buf
.bb_kaddr
;
483 bzero(torb
, sizeof (sbp2_task_mgt_orb_t
));
484 SBP2_ORBP_SET(torb
->to_orb
, orbp
);
485 torb
->to_params
= SBP2_SWAP16(func
| SBP2_ORB_NOTIFY
|
486 SBP2_ORB_RQ_FMT_SBP2
);
487 torb
->to_login_id
= SBP2_SWAP16(id
);
488 SBP2_ADDR_SET(torb
->to_status_fifo
, tp
->t_mgt_status_fifo_buf
.bb_baddr
,
491 ret
= sbp2_tgt_mgt_request(tp
, berr
);
493 sbp2_mgt_agent_release(tp
);
499 sbp2_tgt_reset(sbp2_tgt_t
*tp
, int *berr
)
501 sbp2_lun_t
*lp
= &tp
->t_lun
[0];
504 /* issue TARGET RESET */
505 if ((ret
= sbp2_tgt_task_mgt_request(tp
, lp
->l_login_resp
.lr_login_id
,
506 SBP2_ORB_MGT_FUNC_TARGET_RESET
, 0, berr
)) != SBP2_SUCCESS
) {
510 return (SBP2_SUCCESS
);
514 sbp2_tgt_get_cfgrom(sbp2_tgt_t
*tp
, sbp2_cfgrom_t
**crpp
)
516 *crpp
= &tp
->t_cfgrom
;
517 return (SBP2_SUCCESS
);
521 sbp2_tgt_get_lun_cnt(sbp2_tgt_t
*tp
)
523 return (tp
->t_nluns
);
527 sbp2_tgt_get_lun(sbp2_tgt_t
*tp
, int num
)
529 if (num
< tp
->t_nluns
) {
530 return (&tp
->t_lun
[num
]);
542 sbp2_lun_reset(sbp2_lun_t
*lp
, int *berr
)
544 sbp2_tgt_t
*tp
= lp
->l_tgt
;
545 sbp2_ses_t
*sp
= lp
->l_ses
;
546 sbp2_task_t
*task
= NULL
;
549 /* issue LOGICAL UNIT RESET */
550 if ((ret
= sbp2_tgt_task_mgt_request(tp
, lp
->l_login_resp
.lr_login_id
,
551 SBP2_ORB_MGT_FUNC_LUN_RESET
, 0, berr
)) != SBP2_SUCCESS
) {
555 /* mark all pending tasks reset and notify the driver */
556 mutex_enter(&sp
->s_task_mutex
);
557 for (task
= sp
->s_task_head
; task
!= NULL
; task
= task
->ts_next
) {
558 if (task
->ts_state
< SBP2_TASK_COMP
) {
559 task
->ts_error
= SBP2_TASK_ERR_LUN_RESET
;
560 task
->ts_state
= SBP2_TASK_COMP
;
563 mutex_exit(&sp
->s_task_mutex
);
565 sp
->s_status_cb(sp
->s_status_cb_arg
, NULL
);
567 return (SBP2_SUCCESS
);
571 sbp2_lun_login(sbp2_lun_t
*lp
, sbp2_ses_t
**spp
,
572 void (*cb
)(void *, sbp2_task_t
*), void *cb_arg
, int *berr
)
574 sbp2_tgt_t
*tp
= lp
->l_tgt
;
576 sbp2_login_orb_t
*lorb
;
580 return (SBP2_EINVAL
);
583 /* multiple sessions not supported yet */
584 if (lp
->l_ses
!= NULL
) {
585 return (SBP2_EALREADY
);
588 if ((ret
= sbp2_ses_init(&sp
, lp
, cb
, cb_arg
)) != SBP2_SUCCESS
) {
593 sbp2_mgt_agent_acquire(tp
);
595 /* prepare login ORB */
596 mutex_enter(&tp
->t_mutex
);
597 lorb
= (sbp2_login_orb_t
*)tp
->t_mgt_orb_buf
.bb_kaddr
;
598 bzero(lorb
, sizeof (sbp2_login_orb_t
));
599 SBP2_ADDR_SET(lorb
->lo_resp
, tp
->t_mgt_login_resp_buf
.bb_baddr
, 0);
600 lorb
->lo_params
= SBP2_SWAP16(SBP2_ORB_MGT_FUNC_LOGIN
|
601 SBP2_ORB_LOGIN_EXCL
| SBP2_ORB_NOTIFY
| SBP2_ORB_RQ_FMT_SBP2
);
602 lorb
->lo_lun
= SBP2_SWAP16(lp
->l_lun
);
603 lorb
->lo_resp_len
= SBP2_SWAP16(tp
->t_mgt_login_resp_buf
.bb_len
);
604 SBP2_ADDR_SET(lorb
->lo_status_fifo
, sp
->s_status_fifo_buf
.bb_baddr
, 0);
606 bzero(tp
->t_mgt_login_resp_buf
.bb_kaddr
, sizeof (sbp2_login_resp_t
));
608 lp
->l_logged_in
= B_FALSE
;
609 mutex_exit(&tp
->t_mutex
);
612 if ((ret
= sbp2_tgt_mgt_request(tp
, berr
)) != SBP2_SUCCESS
) {
613 sbp2_mgt_agent_release(tp
);
614 sbp2_ses_fini(lp
->l_ses
);
619 /* retrieve response data (XXX sanity checks?) */
620 mutex_enter(&tp
->t_mutex
);
621 (void) SBP2_SYNC_BUF(tp
, &tp
->t_mgt_login_resp_buf
, 0, 0,
622 DDI_DMA_SYNC_FORKERNEL
);
623 bcopy(tp
->t_mgt_login_resp_buf
.bb_kaddr
, &lp
->l_login_resp
,
624 sizeof (sbp2_login_resp_t
));
626 /* convert from BE to native endianness */
627 SBP2_SWAP16_1(lp
->l_login_resp
.lr_len
);
628 SBP2_SWAP16_1(lp
->l_login_resp
.lr_login_id
);
629 SBP2_SWAP32_2(lp
->l_login_resp
.lr_cmd_agent
);
630 SBP2_SWAP16_1(lp
->l_login_resp
.lr_reconnect_hold
);
631 lp
->l_login_resp
.lr_reconnect_hold
++;
633 sp
->s_agent_offset
= SBP2_ADDR2UINT64(lp
->l_login_resp
.lr_cmd_agent
);
635 lp
->l_logged_in
= B_TRUE
;
636 mutex_exit(&tp
->t_mutex
);
638 sbp2_mgt_agent_release(tp
);
640 if ((ret
= sbp2_agent_init(&sp
->s_agent
, sp
->s_agent_offset
, tp
)) !=
648 return (SBP2_SUCCESS
);
653 sbp2_lun_logout(sbp2_lun_t
*lp
, sbp2_ses_t
**sp
, int *berr
, boolean_t phys
)
655 sbp2_tgt_t
*tp
= lp
->l_tgt
;
657 ASSERT(*sp
== lp
->l_ses
);
659 mutex_enter(&tp
->t_mutex
);
660 if (lp
->l_logged_in
) {
661 lp
->l_logged_in
= B_FALSE
;
662 /* do physical LOGOUT if requested */
664 mutex_exit(&tp
->t_mutex
);
665 sbp2_lun_logout_orb(lp
, tp
, berr
);
666 mutex_enter(&tp
->t_mutex
);
670 sbp2_agent_fini(&lp
->l_ses
->s_agent
);
671 sbp2_ses_fini(lp
->l_ses
);
674 mutex_exit(&tp
->t_mutex
);
676 return (SBP2_SUCCESS
);
680 * Issue LOGOUT mgt orb and wait for response. We are not interested in
681 * the success at the time, since the device may be disconnected or hung,
682 * just trying to make the best effort.
685 sbp2_lun_logout_orb(sbp2_lun_t
*lp
, sbp2_tgt_t
*tp
, int *berr
)
687 sbp2_logout_orb_t
*lorb
;
689 sbp2_mgt_agent_acquire(tp
);
691 /* prepare logout ORB */
692 lorb
= (sbp2_logout_orb_t
*)tp
->t_mgt_orb_buf
.bb_kaddr
;
693 bzero(lorb
, sizeof (sbp2_logout_orb_t
));
694 lorb
->lo_params
= SBP2_SWAP16(SBP2_ORB_MGT_FUNC_LOGOUT
|
695 SBP2_ORB_NOTIFY
| SBP2_ORB_RQ_FMT_SBP2
);
696 lorb
->lo_login_id
= SBP2_SWAP16(lp
->l_login_resp
.lr_login_id
);
697 SBP2_ADDR_SET(lorb
->lo_status_fifo
, tp
->t_mgt_status_fifo_buf
.bb_baddr
,
701 (void) sbp2_tgt_mgt_request(tp
, berr
);
703 sbp2_mgt_agent_release(tp
);
707 sbp2_lun_accepting_tasks(sbp2_lun_t
*lp
)
709 sbp2_tgt_t
*tp
= lp
->l_tgt
;
712 mutex_enter(&tp
->t_mutex
);
713 ret
= ((lp
->l_ses
!= NULL
) && lp
->l_logged_in
&& !lp
->l_reconnecting
);
714 mutex_exit(&tp
->t_mutex
);
720 * --- session routines
724 sbp2_ses_init(sbp2_ses_t
**spp
, sbp2_lun_t
*lp
,
725 void (*cb
)(void *, sbp2_task_t
*), void *cb_arg
)
727 sbp2_tgt_t
*tp
= lp
->l_tgt
;
731 sp
= kmem_zalloc(sizeof (sbp2_ses_t
), KM_SLEEP
);
735 sp
->s_status_cb
= cb
;
736 sp
->s_status_cb_arg
= cb_arg
;
738 mutex_init(&sp
->s_mutex
, NULL
, MUTEX_DRIVER
,
739 SBP2_GET_IBLOCK_COOKIE(tp
));
740 mutex_init(&sp
->s_task_mutex
, NULL
, MUTEX_DRIVER
,
741 SBP2_GET_IBLOCK_COOKIE(tp
));
744 * status FIFO for block requests
746 sp
->s_status_fifo_buf
.bb_len
= sizeof (sbp2_status_t
);
747 sp
->s_status_fifo_buf
.bb_flags
= SBP2_BUS_BUF_WR_POSTED
;
748 sp
->s_status_fifo_buf
.bb_wb_cb
= sbp2_status_fifo_wb_cb
;
749 sp
->s_status_fifo_buf
.bb_sbp2_priv
= sp
;
750 if ((ret
= SBP2_ALLOC_BUF(tp
, &sp
->s_status_fifo_buf
)) !=
757 return (SBP2_SUCCESS
);
762 sbp2_ses_fini(sbp2_ses_t
*sp
)
764 sbp2_tgt_t
*tp
= sp
->s_lun
->l_tgt
;
766 if (sp
->s_status_fifo_buf
.bb_hdl
!= NULL
) {
767 SBP2_FREE_BUF(tp
, &sp
->s_status_fifo_buf
);
770 mutex_destroy(&sp
->s_task_mutex
);
771 mutex_destroy(&sp
->s_mutex
);
773 kmem_free(sp
, sizeof (sbp2_ses_t
));
777 sbp2_ses_reconnect(sbp2_ses_t
*sp
, int *berr
, uint16_t nodeID
)
779 sbp2_tgt_t
*tp
= sp
->s_tgt
;
780 sbp2_lun_t
*lp
= sp
->s_lun
;
783 /* prevent new tasks from being submitted */
784 mutex_enter(&tp
->t_mutex
);
785 lp
->l_reconnecting
= B_TRUE
;
786 mutex_exit(&tp
->t_mutex
);
789 * From 10.5 Task management event matrix:
790 * Immediately upon detection of a bus reset, all command
791 * block fetch agents transition to the reset state and
792 * their associated task sets are cleared without
793 * the return of completion status.
795 * Reset pending tasks so we can retry them later.
797 sbp2_ses_reset_pending_tasks(sp
, nodeID
);
799 ret
= sbp2_ses_reconnect_orb(sp
, berr
);
801 mutex_enter(&tp
->t_mutex
);
802 lp
->l_reconnecting
= B_FALSE
;
803 mutex_exit(&tp
->t_mutex
);
809 * Send reconnect ORB. If operation fails, set lp->l_logged_in = B_FALSE.
812 sbp2_ses_reconnect_orb(sbp2_ses_t
*sp
, int *berr
)
814 sbp2_tgt_t
*tp
= sp
->s_tgt
;
815 sbp2_lun_t
*lp
= sp
->s_lun
;
816 sbp2_agent_t
*ap
= &sp
->s_agent
;
817 sbp2_reconnect_orb_t
*rorb
;
820 sbp2_mgt_agent_acquire(tp
);
822 /* prepare login ORB */
823 rorb
= (sbp2_reconnect_orb_t
*)tp
->t_mgt_orb_buf
.bb_kaddr
;
824 bzero(rorb
, sizeof (sbp2_reconnect_orb_t
));
825 rorb
->ro_params
= SBP2_SWAP16(SBP2_ORB_MGT_FUNC_RECONNECT
|
826 SBP2_ORB_NOTIFY
| SBP2_ORB_RQ_FMT_SBP2
);
827 rorb
->ro_login_id
= SBP2_SWAP16(lp
->l_login_resp
.lr_login_id
);
828 SBP2_ADDR_SET(rorb
->ro_status_fifo
, tp
->t_mgt_status_fifo_buf
.bb_baddr
,
832 if ((ret
= sbp2_tgt_mgt_request(tp
, berr
)) != SBP2_SUCCESS
) {
833 mutex_enter(&tp
->t_mutex
);
834 lp
->l_logged_in
= B_FALSE
;
835 mutex_exit(&tp
->t_mutex
);
837 /* after successful reset fetch agent is in RESET state */
838 mutex_enter(&ap
->a_mutex
);
839 ap
->a_state
= SBP2_AGENT_STATE_RESET
;
840 mutex_exit(&ap
->a_mutex
);
843 sbp2_mgt_agent_release(tp
);
850 sbp2_ses_orbp2task(sbp2_ses_t
*sp
, uint64_t orbp
)
854 mutex_enter(&sp
->s_task_mutex
);
855 for (task
= sp
->s_task_head
; task
!= NULL
; task
= task
->ts_next
) {
856 if (task
->ts_buf
->bb_baddr
== orbp
) {
860 mutex_exit(&sp
->s_task_mutex
);
865 * This is where tasks (command ORB's) are signalled to the target.
866 * 'task' argument is allowed to be NULL, in which case the task will be
867 * taken from the current task list.
869 * Tasks are signalled one at a time by writing into ORB_POINTER register.
870 * While SBP-2 allows dynamic task list updates and using DOORBELL register,
871 * some devices have bugs that prevent using this strategy: e.g. some LaCie
872 * HDD's can corrupt data. Data integrity is more important than performance.
875 sbp2_ses_submit_task(sbp2_ses_t
*sp
, sbp2_task_t
*new_task
)
877 sbp2_agent_t
*ap
= &sp
->s_agent
;
878 sbp2_tgt_t
*tp
= sp
->s_tgt
;
879 sbp2_task_t
*task
; /* task actually being submitted */
881 timeout_id_t timeout_id
;
884 if (!sbp2_lun_accepting_tasks(sp
->s_lun
)) {
885 return (SBP2_ENODEV
);
888 sbp2_agent_acquire(ap
); /* serialize */
890 mutex_enter(&ap
->a_mutex
);
892 /* if task provided, append it to the list */
893 if (new_task
!= NULL
) {
894 ASSERT(new_task
->ts_state
== SBP2_TASK_INIT
);
895 sbp2_ses_append_task(sp
, new_task
);
898 /* if there is already a task in flight, exit */
899 if ((ap
->a_active_task
!= NULL
) &&
900 (ap
->a_active_task
->ts_state
== SBP2_TASK_PEND
)) {
901 mutex_exit(&ap
->a_mutex
);
902 sbp2_agent_release(ap
);
903 return (SBP2_SUCCESS
);
907 * cannot submit tasks from interrupt context,
908 * upper layer driver is responsible to call nudge
910 if (servicing_interrupt()) {
911 mutex_exit(&ap
->a_mutex
);
912 sbp2_agent_release(ap
);
913 return (SBP2_ECONTEXT
);
916 /* no active task, grab the first one on the list in INIT state */
917 ap
->a_active_task
= sbp2_ses_find_task_state(sp
, SBP2_TASK_INIT
);
918 if (ap
->a_active_task
== NULL
) {
919 mutex_exit(&ap
->a_mutex
);
920 sbp2_agent_release(ap
);
921 return (SBP2_SUCCESS
);
923 task
= ap
->a_active_task
;
925 task
->ts_state
= SBP2_TASK_PEND
;
927 /* can't work with a dead agent */
928 if (sbp2_agent_keepalive(ap
, &task
->ts_bus_error
) != SBP2_SUCCESS
) {
929 task
->ts_error
= SBP2_TASK_ERR_DEAD
;
934 * In theory, we should schedule task timeout after it's been submitted.
935 * However, some fast tasks complete even before timeout is scheduled.
936 * To avoid additional complications in the code, schedule timeout now.
938 ASSERT(task
->ts_timeout_id
== 0);
939 task
->ts_time_start
= gethrtime();
940 if (task
->ts_timeout
> 0) {
941 task
->ts_timeout_id
= timeout(sbp2_task_timeout
, task
,
942 task
->ts_timeout
* drv_usectohz(1000000));
945 /* notify fetch agent */
946 ap
->a_state
= SBP2_AGENT_STATE_ACTIVE
;
947 mutex_exit(&ap
->a_mutex
);
948 ret
= sbp2_agent_write_orbp(ap
, task
->ts_buf
->bb_baddr
,
949 &task
->ts_bus_error
);
950 tp
->t_stat
.stat_submit_orbp
++;
951 mutex_enter(&ap
->a_mutex
);
953 if (ret
!= SBP2_SUCCESS
) {
954 ap
->a_state
= SBP2_AGENT_STATE_DEAD
;
955 tp
->t_stat
.stat_status_dead
++;
957 if (task
->ts_timeout_id
!= 0) {
958 timeout_id
= task
->ts_timeout_id
;
959 task
->ts_timeout_id
= 0;
960 (void) untimeout(timeout_id
);
962 task
->ts_error
= SBP2_TASK_ERR_BUS
;
966 mutex_exit(&ap
->a_mutex
);
968 sbp2_agent_release(ap
);
969 return (SBP2_SUCCESS
);
973 * Return immediate error if failed task is the one being submitted,
974 * otherwise use callback.
976 callback
= (ap
->a_active_task
!= new_task
);
977 ASSERT(task
== ap
->a_active_task
);
978 ap
->a_active_task
= NULL
;
979 mutex_exit(&ap
->a_mutex
);
980 sbp2_agent_release(ap
);
983 * Remove task from the list. It is important not to change task state
984 * to SBP2_TASK_COMP while it's still on the list, to avoid race with
985 * upper layer driver (e.g. scsa1394).
987 ret
= sbp2_ses_remove_task(sp
, task
);
988 ASSERT(ret
== SBP2_SUCCESS
);
989 task
->ts_state
= SBP2_TASK_COMP
;
992 sp
->s_status_cb(sp
->s_status_cb_arg
, task
);
993 return (SBP2_SUCCESS
);
995 /* upper layer driver is responsible to call nudge */
996 return (SBP2_FAILURE
);
1001 sbp2_ses_nudge(sbp2_ses_t
*sp
)
1003 (void) sbp2_ses_submit_task(sp
, NULL
);
1007 * append task to the task list
1010 sbp2_ses_append_task(sbp2_ses_t
*sp
, sbp2_task_t
*task
)
1012 sbp2_tgt_t
*tp
= sp
->s_tgt
;
1014 mutex_enter(&sp
->s_task_mutex
);
1015 if (sp
->s_task_head
== NULL
) {
1016 ASSERT(sp
->s_task_tail
== NULL
);
1017 ASSERT(sp
->s_task_cnt
== 0);
1018 task
->ts_prev
= task
->ts_next
= NULL
;
1019 sp
->s_task_head
= sp
->s_task_tail
= task
;
1021 ASSERT(sp
->s_task_cnt
> 0);
1022 task
->ts_next
= NULL
;
1023 task
->ts_prev
= sp
->s_task_tail
;
1024 sp
->s_task_tail
->ts_next
= task
;
1025 sp
->s_task_tail
= task
;
1027 ASSERT(task
!= task
->ts_prev
);
1028 ASSERT(task
!= task
->ts_next
);
1031 if (sp
->s_task_cnt
> tp
->t_stat
.stat_task_max
) {
1032 tp
->t_stat
.stat_task_max
= sp
->s_task_cnt
;
1034 mutex_exit(&sp
->s_task_mutex
);
1038 * remove task from the task list
1041 sbp2_ses_remove_task_locked(sbp2_ses_t
*sp
, sbp2_task_t
*task
)
1044 if (task
== sp
->s_task_head
) { /* first */
1045 ASSERT(task
->ts_prev
== NULL
);
1046 if (task
->ts_next
== NULL
) { /* and last */
1047 ASSERT(sp
->s_task_cnt
== 0);
1048 sp
->s_task_head
= sp
->s_task_tail
= NULL
;
1049 } else { /* but not last */
1050 sp
->s_task_head
= task
->ts_next
;
1051 sp
->s_task_head
->ts_prev
= NULL
;
1053 } else if (task
== sp
->s_task_tail
) { /* last but not first */
1054 ASSERT(task
->ts_next
== NULL
);
1055 sp
->s_task_tail
= task
->ts_prev
;
1056 sp
->s_task_tail
->ts_next
= NULL
;
1057 } else { /* in the middle */
1058 task
->ts_prev
->ts_next
= task
->ts_next
;
1059 task
->ts_next
->ts_prev
= task
->ts_prev
;
1061 task
->ts_prev
= task
->ts_next
= NULL
;
1062 ASSERT(sp
->s_task_cnt
>= 0);
1064 return (SBP2_SUCCESS
);
1068 sbp2_ses_remove_task(sbp2_ses_t
*sp
, sbp2_task_t
*task
)
1072 mutex_enter(&sp
->s_task_mutex
);
1073 ret
= sbp2_ses_remove_task_locked(sp
, task
);
1074 mutex_exit(&sp
->s_task_mutex
);
1080 * Return first task on the list in specified state.
1083 sbp2_ses_find_task_state(sbp2_ses_t
*sp
, sbp2_task_state_t state
)
1085 sbp2_task_t
*task
= NULL
;
1087 mutex_enter(&sp
->s_task_mutex
);
1088 for (task
= sp
->s_task_head
; task
!= NULL
; task
= task
->ts_next
) {
1089 if (task
->ts_state
== state
) {
1093 mutex_exit(&sp
->s_task_mutex
);
1099 * Remove first task on the list. Returns pointer to the removed task or NULL.
1102 sbp2_ses_remove_first_task(sbp2_ses_t
*sp
)
1104 sbp2_task_t
*task
= NULL
;
1106 mutex_enter(&sp
->s_task_mutex
);
1107 task
= sp
->s_task_head
;
1109 (void) sbp2_ses_remove_task_locked(sp
, task
);
1111 mutex_exit(&sp
->s_task_mutex
);
1117 * Remove first task on the list only if it's in specified state.
1118 * Returns pointer to the removed task or NULL.
1121 sbp2_ses_remove_first_task_state(sbp2_ses_t
*sp
, sbp2_task_state_t state
)
1123 sbp2_task_t
*task
= NULL
;
1125 mutex_enter(&sp
->s_task_mutex
);
1126 if ((sp
->s_task_head
!= NULL
) && (sp
->s_task_head
->ts_state
== state
)) {
1127 task
= sp
->s_task_head
;
1128 (void) sbp2_ses_remove_task_locked(sp
, task
);
1130 mutex_exit(&sp
->s_task_mutex
);
1136 * Remove first task on the list. If there's timeout, untimeout it.
1137 * Returns pointer to the removed task or NULL.
1140 sbp2_ses_cancel_first_task(sbp2_ses_t
*sp
)
1142 sbp2_task_t
*task
= NULL
;
1143 timeout_id_t timeout_id
;
1145 mutex_enter(&sp
->s_task_mutex
);
1146 task
= sp
->s_task_head
;
1148 (void) sbp2_ses_remove_task_locked(sp
, task
);
1150 mutex_exit(&sp
->s_task_mutex
);
1152 if ((task
!= NULL
) && ((timeout_id
= task
->ts_timeout_id
) != 0)) {
1153 task
->ts_timeout_id
= 0;
1154 (void) untimeout(timeout_id
);
1161 * Reset pending tasks on the list to their initial state.
1164 sbp2_ses_reset_pending_tasks(sbp2_ses_t
*sp
, uint16_t nodeID
)
1166 sbp2_agent_t
*ap
= &sp
->s_agent
;
1167 sbp2_task_t
*task
= NULL
;
1168 timeout_id_t timeout_id
;
1169 sbp2_cmd_orb_t
*orb
;
1171 mutex_enter(&sp
->s_task_mutex
);
1172 for (task
= sp
->s_task_head
; task
!= NULL
; task
= task
->ts_next
) {
1173 task
->ts_state
= SBP2_TASK_INIT
;
1175 /* cancel timeout */
1176 if ((timeout_id
= task
->ts_timeout_id
) != 0) {
1177 task
->ts_timeout_id
= 0;
1178 (void) untimeout(timeout_id
);
1181 /* update ORB nodeID */
1182 orb
= (sbp2_cmd_orb_t
*)sbp2_task_orb_kaddr(task
);
1183 *(uint16_t *)orb
->co_data_descr
= SBP2_SWAP16(nodeID
);
1184 sbp2_task_orb_sync(sp
->s_lun
, task
, DDI_DMA_SYNC_FORDEV
);
1186 mutex_exit(&sp
->s_task_mutex
);
1188 mutex_enter(&ap
->a_mutex
);
1189 ap
->a_active_task
= NULL
;
1190 mutex_exit(&ap
->a_mutex
);
1194 sbp2_ses_agent_reset(sbp2_ses_t
*sp
, int *berr
)
1196 return (sbp2_agent_reset(&sp
->s_agent
, berr
));
1200 sbp2_ses_abort_task(sbp2_ses_t
*sp
, sbp2_task_t
*task
, int *berr
)
1202 sbp2_tgt_t
*tp
= sp
->s_tgt
;
1203 sbp2_lun_t
*lp
= sp
->s_lun
;
1205 sbp2_cmd_orb_t
*orb
= (sbp2_cmd_orb_t
*)task
->ts_buf
->bb_kaddr
;
1206 int ret
= SBP2_SUCCESS
;
1208 /* mark ORB as dummy ORB */
1209 params
= (orb
->co_params
& ~SBP2_ORB_RQ_FMT
) | SBP2_ORB_RQ_FMT_DUMMY
;
1210 orb
->co_params
= params
;
1211 (void) SBP2_SYNC_BUF(tp
, task
->ts_buf
, 0, 0, DDI_DMA_SYNC_FORDEV
);
1213 ret
= sbp2_tgt_task_mgt_request(tp
, lp
->l_login_resp
.lr_login_id
,
1214 SBP2_ORB_MGT_FUNC_ABORT_TASK
, task
->ts_buf
->bb_baddr
, berr
);
1221 sbp2_ses_abort_task_set(sbp2_ses_t
*sp
, int *berr
)
1223 sbp2_tgt_t
*tp
= sp
->s_tgt
;
1224 sbp2_lun_t
*lp
= sp
->s_lun
;
1227 ret
= sbp2_tgt_task_mgt_request(tp
, lp
->l_login_resp
.lr_login_id
,
1228 SBP2_ORB_MGT_FUNC_ABORT_TASK_SET
, 0, berr
);
1238 * allocate ORB resources
1240 * we maintain a freelist of ORB's for faster allocation
1243 static sbp2_bus_buf_t
*
1244 sbp2_orb_freelist_get(sbp2_lun_t
*lp
, sbp2_task_t
*task
, int len
)
1246 sbp2_buf_list_t
*bl
= &lp
->l_orb_freelist
;
1247 sbp2_bus_buf_t
*buf
= NULL
;
1249 mutex_enter(&bl
->bl_mutex
);
1250 if ((bl
->bl_head
!= NULL
) && (bl
->bl_head
->bb_len
== len
)) {
1252 bl
->bl_head
= buf
->bb_next
;
1253 if (bl
->bl_tail
== buf
) { /* last one? */
1254 ASSERT(bl
->bl_head
== NULL
);
1258 buf
->bb_next
= NULL
;
1260 mutex_exit(&bl
->bl_mutex
);
1266 sbp2_orb_freelist_put(sbp2_lun_t
*lp
, sbp2_bus_buf_t
*buf
)
1268 sbp2_buf_list_t
*bl
= &lp
->l_orb_freelist
;
1271 mutex_enter(&bl
->bl_mutex
);
1272 if (bl
->bl_len
< SBP2_ORB_FREELIST_MAX
) {
1273 if (bl
->bl_head
== NULL
) {
1274 ASSERT(bl
->bl_tail
== NULL
);
1275 bl
->bl_head
= bl
->bl_tail
= buf
;
1277 bl
->bl_tail
->bb_next
= buf
;
1280 buf
->bb_next
= NULL
;
1286 mutex_exit(&bl
->bl_mutex
);
1292 sbp2_orb_freelist_destroy(sbp2_lun_t
*lp
)
1294 sbp2_tgt_t
*tp
= lp
->l_tgt
;
1295 sbp2_buf_list_t
*bl
= &lp
->l_orb_freelist
;
1296 sbp2_bus_buf_t
*buf
, *buf_next
;
1298 mutex_enter(&bl
->bl_mutex
);
1299 for (buf
= bl
->bl_head
; buf
!= NULL
; ) {
1300 SBP2_FREE_BUF(tp
, buf
);
1301 buf_next
= buf
->bb_next
;
1302 kmem_free(buf
, sizeof (sbp2_bus_buf_t
));
1305 bl
->bl_head
= bl
->bl_tail
= NULL
;
1306 mutex_exit(&bl
->bl_mutex
);
1310 sbp2_task_orb_alloc(sbp2_lun_t
*lp
, sbp2_task_t
*task
, int len
)
1312 sbp2_tgt_t
*tp
= lp
->l_tgt
;
1316 buf_len
= SBP2_ORB_SIZE_ROUNDUP(tp
, len
);
1318 /* try freelist first */
1319 if ((task
->ts_buf
= sbp2_orb_freelist_get(lp
, task
, buf_len
)) != NULL
) {
1320 return (SBP2_SUCCESS
);
1323 /* if no free buffers, allocate new */
1324 task
->ts_buf
= kmem_zalloc(sizeof (sbp2_bus_buf_t
), KM_SLEEP
);
1325 task
->ts_buf
->bb_len
= buf_len
;
1326 task
->ts_buf
->bb_flags
= SBP2_BUS_BUF_DMA
| SBP2_BUS_BUF_RD
;
1327 if ((ret
= SBP2_ALLOC_BUF(tp
, task
->ts_buf
)) != SBP2_SUCCESS
) {
1328 kmem_free(task
->ts_buf
, sizeof (sbp2_bus_buf_t
));
1329 task
->ts_buf
= NULL
;
1336 sbp2_task_orb_free(sbp2_lun_t
*lp
, sbp2_task_t
*task
)
1338 sbp2_tgt_t
*tp
= lp
->l_tgt
;
1340 if (task
->ts_buf
!= NULL
) {
1341 if (sbp2_orb_freelist_put(lp
, task
->ts_buf
) != SBP2_SUCCESS
) {
1342 SBP2_FREE_BUF(tp
, task
->ts_buf
);
1343 kmem_free(task
->ts_buf
, sizeof (sbp2_bus_buf_t
));
1345 task
->ts_buf
= NULL
;
1350 sbp2_task_orb_kaddr(sbp2_task_t
*task
)
1352 return (task
->ts_buf
->bb_kaddr
);
1356 sbp2_task_orb_sync(sbp2_lun_t
*lp
, sbp2_task_t
*task
, int flags
)
1358 (void) SBP2_SYNC_BUF(lp
->l_tgt
, task
->ts_buf
, 0, 0, flags
);
1363 * --- fetch agent routines
1367 sbp2_agent_init(sbp2_agent_t
*ap
, uint64_t offset
, sbp2_tgt_t
*tp
)
1373 return (SBP2_FAILURE
);
1378 ap
->a_reg_agent_state
= offset
+ SBP2_AGENT_STATE_OFFSET
;
1379 ap
->a_reg_agent_reset
= offset
+ SBP2_AGENT_RESET_OFFSET
;
1380 ap
->a_reg_orbp
= offset
+ SBP2_ORB_POINTER_OFFSET
;
1381 ap
->a_reg_doorbell
= offset
+ SBP2_DOORBELL_OFFSET
;
1382 ap
->a_reg_unsol_status_enable
= offset
+
1383 SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET
;
1386 * allocate bus commands
1388 if ((ret
= SBP2_ALLOC_CMD(tp
, &ap
->a_cmd
, 0)) != SBP2_SUCCESS
) {
1391 ap
->a_cmd_data
= allocb(sizeof (sbp2_orbp_t
), BPRI_HI
);
1392 if (ap
->a_cmd_data
== NULL
) {
1393 sbp2_agent_fini(ap
);
1394 return (SBP2_ENOMEM
);
1397 mutex_init(&ap
->a_mutex
, NULL
, MUTEX_DRIVER
,
1398 SBP2_GET_IBLOCK_COOKIE(tp
));
1399 cv_init(&ap
->a_cv
, NULL
, CV_DRIVER
, NULL
);
1402 ap
->a_state
= SBP2_AGENT_STATE_RESET
;
1405 return (SBP2_SUCCESS
);
1410 sbp2_agent_fini(sbp2_agent_t
*ap
)
1412 sbp2_tgt_t
*tp
= ap
->a_tgt
;
1414 /* free bus commands */
1415 if (ap
->a_cmd
!= NULL
) {
1416 SBP2_FREE_CMD(tp
, ap
->a_cmd
);
1418 if (ap
->a_cmd_data
!= NULL
) {
1419 freeb(ap
->a_cmd_data
);
1421 cv_destroy(&ap
->a_cv
);
1422 mutex_destroy(&ap
->a_mutex
);
1427 sbp2_agent_acquire_locked(sbp2_agent_t
*ap
)
1429 while (ap
->a_acquired
) {
1430 cv_wait(&ap
->a_cv
, &ap
->a_mutex
);
1432 ap
->a_acquired
= B_TRUE
;
1437 sbp2_agent_release_locked(sbp2_agent_t
*ap
)
1439 ap
->a_acquired
= B_FALSE
;
1440 cv_signal(&ap
->a_cv
); /* wake next waiter */
1445 sbp2_agent_acquire(sbp2_agent_t
*ap
)
1447 mutex_enter(&ap
->a_mutex
);
1448 sbp2_agent_acquire_locked(ap
);
1449 mutex_exit(&ap
->a_mutex
);
1454 sbp2_agent_release(sbp2_agent_t
*ap
)
1456 mutex_enter(&ap
->a_mutex
);
1457 sbp2_agent_release_locked(ap
);
1458 mutex_exit(&ap
->a_mutex
);
1463 sbp2_agent_keepalive(sbp2_agent_t
*ap
, int *berr
)
1466 int ret
= SBP2_SUCCESS
;
1468 ASSERT(mutex_owned(&ap
->a_mutex
));
1470 if (ap
->a_state
== SBP2_AGENT_STATE_DEAD
) {
1471 acquired
= ap
->a_acquired
;
1473 sbp2_agent_acquire_locked(ap
);
1476 mutex_exit(&ap
->a_mutex
);
1477 ret
= sbp2_agent_reset(ap
, berr
);
1478 mutex_enter(&ap
->a_mutex
);
1481 sbp2_agent_release_locked(ap
);
1490 sbp2_agent_doorbell(sbp2_agent_t
*ap
, int *berr
)
1492 return (SBP2_WQ(ap
->a_tgt
, ap
->a_cmd
, ap
->a_reg_doorbell
, 0, berr
));
1497 * write into ORB_POINTER register and make sure it reached target
1499 * From E.2: "If no acknowledgement is received by the initiator after a write
1500 * to the ORB_POINTER register, the initiator should not retry the write.
1501 * The recommended method for error recovery is a write to the AGENT_RESET
1502 * register." So we can retry, but not in case of timeout.
1505 sbp2_agent_write_orbp(sbp2_agent_t
*ap
, uint64_t baddr
, int *berr
)
1510 SBP2_ORBP_SET(ap
->a_cmd_data
->b_rptr
, baddr
);
1511 ap
->a_cmd_data
->b_wptr
= ap
->a_cmd_data
->b_rptr
+ 8;
1514 ap
->a_tgt
->t_stat
.stat_agent_worbp
++;
1515 if ((ret
= SBP2_WB(ap
->a_tgt
, ap
->a_cmd
, ap
->a_reg_orbp
,
1516 ap
->a_cmd_data
, 8, berr
)) == SBP2_SUCCESS
) {
1519 ap
->a_tgt
->t_stat
.stat_agent_worbp_fail
++;
1521 if ((ret
== SBP2_ETIMEOUT
) ||
1522 (++i
> sbp2_write_orbp_nretries
)) {
1525 if (sbp2_write_orbp_delay
> 0) {
1526 drv_usecwait(sbp2_write_orbp_delay
);
1535 * reset fetch agent by writing into AGENT_RESET register
1538 sbp2_agent_reset(sbp2_agent_t
*ap
, int *berr
)
1544 ap
->a_tgt
->t_stat
.stat_agent_wreset
++;
1545 if ((ret
= SBP2_WQ(ap
->a_tgt
, ap
->a_cmd
, ap
->a_reg_agent_reset
,
1546 0, berr
)) == SBP2_SUCCESS
) {
1547 mutex_enter(&ap
->a_mutex
);
1548 ap
->a_state
= SBP2_AGENT_STATE_RESET
;
1549 mutex_exit(&ap
->a_mutex
);
1553 ap
->a_tgt
->t_stat
.stat_agent_wreset_fail
++;
1554 if (++i
> sbp2_submit_reset_nretries
) {
1557 if (sbp2_submit_reset_delay
> 0) {
1558 drv_usecwait(sbp2_submit_reset_delay
);
1566 * --- callbacks and timeouts
1570 * Status FIFO callback for mgt ORB's.
1574 sbp2_mgt_status_fifo_wb_cb(sbp2_bus_buf_t
*buf
, void *reqh
, mblk_t
**bpp
)
1576 sbp2_tgt_t
*tp
= buf
->bb_sbp2_priv
;
1583 /* 8 bytes minimum */
1585 SBP2_BUF_WR_DONE(tp
, buf
, reqh
, SBP2_BUS_BUF_ELENGTH
);
1586 tp
->t_stat
.stat_status_short
++;
1590 /* convert 2-quadlet header from BE to native endianness */
1591 st
= (sbp2_status_t
*)(*bpp
)->b_rptr
;
1592 SBP2_SWAP16_1(st
->st_orb_offset_hi
);
1593 SBP2_SWAP32_1(st
->st_orb_offset_lo
);
1594 orbp
= ((uint64_t)st
->st_orb_offset_hi
<< 32) | st
->st_orb_offset_lo
;
1596 if (orbp
!= tp
->t_mgt_orb_buf
.bb_baddr
) {
1597 SBP2_BUF_WR_DONE(tp
, buf
, reqh
, SBP2_BUS_BUF_FAILURE
);
1598 tp
->t_stat
.stat_status_mgt_notask
++;
1602 /* make a local copy of status block */
1603 bzero(&tp
->t_mgt_status
, sizeof (sbp2_status_t
));
1604 bcopy((*bpp
)->b_rptr
, &tp
->t_mgt_status
, len
);
1606 SBP2_BUF_WR_DONE(tp
, buf
, reqh
, SBP2_BUS_BUF_SUCCESS
);
1608 /* wake up waiter */
1609 mutex_enter(&tp
->t_mutex
);
1610 tp
->t_mgt_status_rcvd
= B_TRUE
;
1611 cv_signal(&tp
->t_mgt_status_cv
);
1612 mutex_exit(&tp
->t_mutex
);
1616 sbp2_task_timeout(void *arg
)
1618 sbp2_task_t
*task
= arg
;
1619 sbp2_ses_t
*sp
= task
->ts_ses
;
1620 sbp2_agent_t
*ap
= &sp
->s_agent
;
1622 mutex_enter(&ap
->a_mutex
);
1625 if (task
->ts_timeout_id
== 0) {
1626 mutex_exit(&ap
->a_mutex
);
1629 task
->ts_timeout_id
= 0;
1630 task
->ts_time_comp
= gethrtime();
1632 /* avoid race with other callbacks */
1633 if (task
->ts_state
!= SBP2_TASK_PEND
) {
1634 mutex_exit(&ap
->a_mutex
);
1638 if (task
== ap
->a_active_task
) {
1639 ap
->a_active_task
= NULL
;
1641 task
->ts_error
= SBP2_TASK_ERR_TIMEOUT
;
1642 task
->ts_state
= SBP2_TASK_COMP
;
1644 /* we mark agent DEAD so it's reset before next task is submitted */
1645 ap
->a_state
= SBP2_AGENT_STATE_DEAD
;
1646 sp
->s_tgt
->t_stat
.stat_status_dead
++;
1647 mutex_exit(&ap
->a_mutex
);
1649 sp
->s_status_cb(sp
->s_status_cb_arg
, task
);
1653 * Status FIFO callback for command ORB's. Also used for login ORB.
1657 sbp2_status_fifo_wb_cb(sbp2_bus_buf_t
*buf
, void *reqh
, mblk_t
**bpp
)
1659 sbp2_ses_t
*sp
= buf
->bb_sbp2_priv
;
1660 sbp2_tgt_t
*tp
= sp
->s_tgt
;
1661 sbp2_agent_t
*ap
= &sp
->s_agent
;
1667 timeout_id_t timeout_id
;
1671 /* 8 bytes minimum */
1673 SBP2_BUF_WR_DONE(tp
, buf
, reqh
, SBP2_BUS_BUF_ELENGTH
);
1674 tp
->t_stat
.stat_status_short
++;
1678 /* convert 2-quadlet header from BE32 to native endianness */
1679 st
= (sbp2_status_t
*)(*bpp
)->b_rptr
;
1680 SBP2_SWAP16_1(st
->st_orb_offset_hi
);
1681 SBP2_SWAP32_1(st
->st_orb_offset_lo
);
1683 orbp
= ((uint64_t)st
->st_orb_offset_hi
<< 32) | st
->st_orb_offset_lo
;
1685 /* login ORB status? */
1686 if (orbp
== tp
->t_mgt_orb_buf
.bb_baddr
) {
1687 bzero(&tp
->t_mgt_status
, sizeof (sbp2_status_t
));
1688 bcopy((*bpp
)->b_rptr
, &tp
->t_mgt_status
, len
);
1690 SBP2_BUF_WR_DONE(tp
, buf
, reqh
, SBP2_BUS_BUF_SUCCESS
);
1692 /* wake up waiter */
1693 mutex_enter(&tp
->t_mutex
);
1694 tp
->t_mgt_status_rcvd
= B_TRUE
;
1695 cv_signal(&tp
->t_mgt_status_cv
);
1696 mutex_exit(&tp
->t_mutex
);
1700 /* dismiss unsolicited status */
1701 src
= st
->st_param
& SBP2_ST_SRC
;
1702 if (src
== SBP2_ST_SRC_UNSOLICITED
) {
1703 SBP2_BUF_WR_DONE(tp
, buf
, reqh
, SBP2_BUS_BUF_FAILURE
);
1704 tp
->t_stat
.stat_status_unsolicited
++;
1708 /* find task corresponding to this ORB pointer */
1709 if ((task
= sbp2_ses_orbp2task(sp
, orbp
)) == NULL
) {
1710 SBP2_BUF_WR_DONE(tp
, buf
, reqh
, SBP2_BUS_BUF_FAILURE
);
1711 tp
->t_stat
.stat_status_notask
++;
1716 * Copy status block into a local buffer.
1718 * Note: (ref: B.2) "SBP-2 permits the return of a status block between
1719 * two and eight quadlets in length. When a truncated status block
1720 * is stored, the omited quadlets shall be interpreted as if zero
1721 * values were stored."
1723 bzero(&task
->ts_status
, sizeof (sbp2_status_t
));
1724 bcopy((*bpp
)->b_rptr
, &task
->ts_status
, len
);
1726 SBP2_BUF_WR_DONE(tp
, buf
, reqh
, SBP2_BUS_BUF_SUCCESS
);
1728 mutex_enter(&ap
->a_mutex
);
1730 if ((timeout_id
= task
->ts_timeout_id
) != 0) {
1731 task
->ts_timeout_id
= 0;
1732 (void) untimeout(timeout_id
);
1735 /* determine agent state */
1736 if (st
->st_param
& SBP2_ST_DEAD
) {
1737 ap
->a_state
= SBP2_AGENT_STATE_DEAD
;
1738 tp
->t_stat
.stat_status_dead
++;
1741 /* avoid race with other callbacks */
1742 if (task
->ts_state
!= SBP2_TASK_PEND
) {
1743 mutex_exit(&ap
->a_mutex
);
1747 if (task
== ap
->a_active_task
) {
1748 ap
->a_active_task
= NULL
;
1750 task
->ts_error
= SBP2_TASK_ERR_NONE
;
1751 task
->ts_state
= SBP2_TASK_COMP
;
1753 mutex_exit(&ap
->a_mutex
);
1755 sp
->s_status_cb(sp
->s_status_cb_arg
, task
); /* notify the driver */
1762 * since mgt agent is shared between LUNs and login sessions,
1763 * it is safer to serialize mgt requests
1766 sbp2_mgt_agent_acquire(sbp2_tgt_t
*tp
)
1768 mutex_enter(&tp
->t_mutex
);
1769 while (tp
->t_mgt_agent_acquired
) {
1770 cv_wait(&tp
->t_mgt_agent_cv
, &tp
->t_mutex
);
1772 tp
->t_mgt_agent_acquired
= B_TRUE
;
1773 mutex_exit(&tp
->t_mutex
);
1777 sbp2_mgt_agent_release(sbp2_tgt_t
*tp
)
1779 mutex_enter(&tp
->t_mutex
);
1780 tp
->t_mgt_agent_acquired
= B_FALSE
;
1781 cv_signal(&tp
->t_mgt_agent_cv
); /* wake next waiter */
1782 mutex_exit(&tp
->t_mutex
);