4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 * 1394 Services Layer Isochronous Communication Routines
32 * This file contains routines for managing isochronous bandwidth
33 * and channel needs for registered targets (through the target
39 #include <sys/sunddi.h>
40 #include <sys/types.h>
41 #include <sys/tnf_probe.h>
43 #include <sys/1394/t1394.h>
44 #include <sys/1394/s1394.h>
45 #include <sys/1394/h1394.h>
46 #include <sys/1394/ieee1394.h>
49 * s1394_isoch_rsrc_realloc()
50 * is called during bus reset processing to reallocate any isochronous
51 * resources that were previously allocated.
54 s1394_isoch_rsrc_realloc(s1394_hal_t
*hal
)
56 s1394_isoch_cec_t
*cec_curr
;
58 uint32_t old_chnl_mask
;
59 uint_t bw_alloc_units
;
65 TNF_PROBE_0_DEBUG(s1394_isoch_rsrc_realloc_enter
,
66 S1394_TNF_SL_ISOCH_STACK
, "");
69 * Get the current generation number - don't need the
70 * topology tree mutex here because it is read-only, and
71 * there is a race condition with or without it.
73 generation
= hal
->generation_count
;
75 /* Lock the Isoch CEC list */
76 mutex_enter(&hal
->isoch_cec_list_mutex
);
78 cec_curr
= hal
->isoch_cec_list_head
;
79 while (cec_curr
!= NULL
) {
80 /* Lock the Isoch CEC member list */
81 mutex_enter(&cec_curr
->isoch_cec_mutex
);
83 /* Are we supposed to reallocate resources? */
84 if (!(cec_curr
->cec_options
& T1394_NO_IRM_ALLOC
) &&
85 (cec_curr
->realloc_valid
== B_TRUE
) &&
86 (cec_curr
->realloc_failed
== B_FALSE
)) {
88 /* Reallocate some bandwidth */
89 bw_alloc_units
= s1394_compute_bw_alloc_units(hal
,
90 cec_curr
->bandwidth
, cec_curr
->realloc_speed
);
92 /* Check that the generation has not changed */
93 if (generation
!= hal
->generation_count
) {
94 /* Try the next Isoch CEC */
98 /* Unlock the Isoch CEC member list */
99 mutex_exit(&cec_curr
->isoch_cec_mutex
);
101 * We can unlock the Isoch CEC list here
102 * because we know this Isoch CEC can not
103 * go away (we are trying to realloc its
104 * resources so it can't be in a state that
105 * will allow a free).
107 mutex_exit(&hal
->isoch_cec_list_mutex
);
109 /* Try to reallocate bandwidth */
110 ret
= s1394_bandwidth_alloc(hal
, bw_alloc_units
,
113 /* Lock the Isoch CEC list */
114 mutex_enter(&hal
->isoch_cec_list_mutex
);
115 /* Lock the Isoch CEC member list */
116 mutex_enter(&cec_curr
->isoch_cec_mutex
);
118 /* If we failed because we couldn't get bandwidth */
119 if (ret
== DDI_FAILURE
) {
120 cec_curr
->realloc_failed
= B_TRUE
;
121 cec_curr
->realloc_fail_reason
=
122 T1394_RSRC_BANDWIDTH
;
126 /* Are we supposed to reallocate resources? */
127 if (!(cec_curr
->cec_options
& T1394_NO_IRM_ALLOC
) &&
128 (cec_curr
->realloc_valid
== B_TRUE
) &&
129 (cec_curr
->realloc_failed
== B_FALSE
)) {
131 /* Reallocate the channel */
132 chnl_num
= cec_curr
->realloc_chnl_num
;
133 chnl_mask
= (1 << ((63 - chnl_num
) % 32));
135 /* Unlock the Isoch CEC member list */
136 mutex_exit(&cec_curr
->isoch_cec_mutex
);
138 * We can unlock the Isoch CEC list here
139 * because we know this Isoch CEC can not
140 * go away (we are trying to realloc its
141 * resources so it can't be in a state that
142 * will allow a free).
144 mutex_exit(&hal
->isoch_cec_list_mutex
);
147 ret
= s1394_channel_alloc(hal
, chnl_mask
,
148 generation
, S1394_CHANNEL_ALLOC_HI
,
149 &old_chnl_mask
, &err
);
151 ret
= s1394_channel_alloc(hal
, chnl_mask
,
152 generation
, S1394_CHANNEL_ALLOC_LO
,
153 &old_chnl_mask
, &err
);
156 /* Lock the Isoch CEC list */
157 mutex_enter(&hal
->isoch_cec_list_mutex
);
158 /* Lock the Isoch CEC member list */
159 mutex_enter(&cec_curr
->isoch_cec_mutex
);
161 if (ret
== DDI_FAILURE
) {
162 if (err
!= CMD1394_EBUSRESET
) {
164 * If we successfully reallocate
165 * bandwidth, and then fail getting
166 * the channel, we need to free up
170 /* Try to free up the bandwidth */
171 ret
= s1394_bandwidth_free(hal
,
172 bw_alloc_units
, generation
, &err
);
173 if ((ret
== DDI_FAILURE
) &&
174 (err
!= CMD1394_EBUSRESET
)) {
176 s1394_isoch_rsrc_realloc_error
,
177 S1394_TNF_SL_ISOCH_ERROR
,
179 "Unable to free bandwidth");
181 /* Try the next Isoch CEC */
184 cec_curr
->realloc_failed
= B_TRUE
;
185 cec_curr
->realloc_fail_reason
=
190 /* Unlock the Isoch CEC member list */
191 mutex_exit(&cec_curr
->isoch_cec_mutex
);
192 cec_curr
= cec_curr
->cec_next
;
195 /* Unlock the Isoch CEC list */
196 mutex_exit(&hal
->isoch_cec_list_mutex
);
197 TNF_PROBE_0_DEBUG(s1394_isoch_rsrc_realloc_exit
,
198 S1394_TNF_SL_ISOCH_STACK
, "");
202 * s1394_isoch_rsrc_realloc_notify()
203 * is called during bus reset processing to notify all targets for
204 * which isochronous resources were not able to be reallocated.
207 s1394_isoch_rsrc_realloc_notify(s1394_hal_t
*hal
)
209 s1394_isoch_cec_t
*cec_curr
;
210 s1394_isoch_cec_member_t
*member_curr
;
211 t1394_isoch_rsrc_error_t fail_arg
;
213 s1394_isoch_cec_type_t type
;
214 void (*rsrc_fail_callback
)(t1394_isoch_cec_handle_t
, opaque_t
,
215 t1394_isoch_rsrc_error_t
);
217 TNF_PROBE_0_DEBUG(s1394_isoch_rsrc_realloc_notify_enter
,
218 S1394_TNF_SL_ISOCH_STACK
, "");
220 /* Lock the Isoch CEC list */
221 mutex_enter(&hal
->isoch_cec_list_mutex
);
223 /* Notify all targets that failed realloc */
224 cec_curr
= hal
->isoch_cec_list_head
;
225 while (cec_curr
!= NULL
) {
226 /* Lock the Isoch CEC member list */
227 mutex_enter(&cec_curr
->isoch_cec_mutex
);
229 /* Do we notify of realloc failure? */
230 if (!(cec_curr
->cec_options
& T1394_NO_IRM_ALLOC
) &&
231 (cec_curr
->realloc_valid
== B_TRUE
) &&
232 (cec_curr
->realloc_failed
== B_TRUE
)) {
234 /* Reason for realloc failure */
235 fail_arg
= cec_curr
->realloc_fail_reason
;
237 /* Now we are going into the callbacks */
238 cec_curr
->in_fail_callbacks
= B_TRUE
;
240 type
= cec_curr
->cec_type
;
242 /* Unlock the Isoch CEC member list */
243 mutex_exit(&cec_curr
->isoch_cec_mutex
);
245 * We can unlock the Isoch CEC list here
246 * because we have the in_fail_callbacks
247 * field set to B_TRUE. And free will fail
248 * if we are in fail callbacks.
250 mutex_exit(&hal
->isoch_cec_list_mutex
);
252 /* Call all of the rsrc_fail_target() callbacks */
253 /* Start at the head (talker first) and */
254 /* go toward the tail (listeners last) */
255 member_curr
= cec_curr
->cec_member_list_head
;
256 while (member_curr
!= NULL
) {
257 rsrc_fail_callback
= member_curr
->
258 isoch_cec_evts
.rsrc_fail_target
;
259 evts_arg
= member_curr
->isoch_cec_evts_arg
;
260 if (rsrc_fail_callback
!= NULL
) {
262 if (type
== S1394_PEER_TO_PEER
) {
264 (t1394_isoch_cec_handle_t
)
269 (t1394_isoch_cec_handle_t
)
274 member_curr
= member_curr
->cec_mem_next
;
277 /* Lock the Isoch CEC list */
278 mutex_enter(&hal
->isoch_cec_list_mutex
);
279 /* Lock the Isoch CEC member list */
280 mutex_enter(&cec_curr
->isoch_cec_mutex
);
282 /* We are finished with the callbacks */
283 cec_curr
->in_fail_callbacks
= B_FALSE
;
284 if (cec_curr
->cec_want_wakeup
== B_TRUE
) {
285 cec_curr
->cec_want_wakeup
= B_FALSE
;
286 cv_broadcast(&cec_curr
->in_callbacks_cv
);
289 /* Set flags back to original state */
290 cec_curr
->realloc_valid
= B_FALSE
;
291 cec_curr
->realloc_failed
= B_FALSE
;
293 /* Unlock the Isoch CEC member list */
294 mutex_exit(&cec_curr
->isoch_cec_mutex
);
295 cec_curr
= cec_curr
->cec_next
;
298 /* Unlock the Isoch CEC list */
299 mutex_exit(&hal
->isoch_cec_list_mutex
);
300 TNF_PROBE_0_DEBUG(s1394_isoch_rsrc_realloc_notify_exit
,
301 S1394_TNF_SL_ISOCH_STACK
, "");
305 * s1394_channel_alloc()
306 * is used to allocate an isochronous channel. A channel mask and
307 * generation are passed. A request is sent to whichever node is the
308 * IRM for the appropriate channels. If it fails because of a bus
309 * reset it can be retried. If it fails for another reason the
310 * channel(s) may not be availble or there may be no IRM.
313 s1394_channel_alloc(s1394_hal_t
*hal
, uint32_t channel_mask
, uint_t generation
,
314 uint_t flags
, uint32_t *old_channels
, int *result
)
317 uint64_t IRM_ID_addr
;
326 int num_retries
= S1394_ISOCH_ALLOC_RETRIES
;
328 TNF_PROBE_0_DEBUG(s1394_channel_alloc_enter
,
329 S1394_TNF_SL_ISOCH_STACK
, "");
331 /* Lock the topology tree */
332 mutex_enter(&hal
->topology_tree_mutex
);
334 hal_node_num
= IEEE1394_NODE_NUM(hal
->node_id
);
335 IRM_node
= hal
->IRM_node
;
337 /* Unlock the topology tree */
338 mutex_exit(&hal
->topology_tree_mutex
);
340 /* Make sure there is a valid IRM on the bus */
341 if (IRM_node
== -1) {
342 *result
= CMD1394_ERETRIES_EXCEEDED
;
343 TNF_PROBE_1(s1394_channel_alloc_error
,
344 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
345 "No IRM on the 1394 bus");
346 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit
,
347 S1394_TNF_SL_ISOCH_STACK
, "");
348 return (DDI_FAILURE
);
351 if (flags
& S1394_CHANNEL_ALLOC_HI
) {
353 (IEEE1394_SCSR_CHANS_AVAIL_HI
& IEEE1394_CSR_OFFSET_MASK
);
356 (IEEE1394_SCSR_CHANS_AVAIL_LO
& IEEE1394_CSR_OFFSET_MASK
);
359 /* Send compare-swap to CHANNELS_AVAILABLE */
360 /* register on the Isoch Rsrc Mgr */
361 if (IRM_node
== hal_node_num
) {
365 (void) HAL_CALL(hal
).csr_read(hal
->halinfo
.hal_private
,
368 /* Check that the generation has not changed */
369 if (generation
!= hal
->generation_count
) {
370 *result
= CMD1394_EBUSRESET
;
371 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit
,
372 S1394_TNF_SL_ISOCH_STACK
, "");
373 return (DDI_FAILURE
);
377 swap
= old_value
& (~channel_mask
);
379 ret
= HAL_CALL(hal
).csr_cswap32(
380 hal
->halinfo
.hal_private
, generation
,
381 offset
, compare
, swap
, &old_value
);
382 if (ret
!= DDI_SUCCESS
) {
383 *result
= CMD1394_EBUSRESET
;
384 TNF_PROBE_1(s1394_channel_alloc_error
,
385 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
386 msg
, "Error in cswap32");
387 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit
,
388 "stacktrace 1394 s1394", "");
389 return (DDI_FAILURE
);
392 if ((~old_value
& channel_mask
) != 0) {
393 *result
= CMD1394_ERETRIES_EXCEEDED
;
394 TNF_PROBE_1(s1394_channel_alloc_error
,
395 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
396 msg
, "Channels already taken");
397 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit
,
398 S1394_TNF_SL_ISOCH_STACK
, "");
399 return (DDI_FAILURE
);
402 if (old_value
== compare
) {
403 *result
= CMD1394_CMDSUCCESS
;
404 *old_channels
= old_value
;
406 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit
,
407 S1394_TNF_SL_ISOCH_STACK
, "");
408 return (DDI_SUCCESS
);
412 *result
= CMD1394_ERETRIES_EXCEEDED
;
413 TNF_PROBE_1(s1394_channel_alloc_error
,
414 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
416 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit
,
417 S1394_TNF_SL_ISOCH_STACK
, "");
418 return (DDI_FAILURE
);
422 if (s1394_alloc_cmd(hal
, 0, &cmd
) != DDI_SUCCESS
) {
423 *result
= CMD1394_EUNKNOWN_ERROR
;
424 TNF_PROBE_1(s1394_channel_alloc_error
,
425 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
426 "Unable to allocate command");
427 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit
,
428 S1394_TNF_SL_ISOCH_STACK
, "");
429 return (DDI_FAILURE
);
432 cmd
->cmd_options
= (CMD1394_CANCEL_ON_BUS_RESET
|
433 CMD1394_OVERRIDE_ADDR
| CMD1394_BLOCKING
);
434 cmd
->cmd_type
= CMD1394_ASYNCH_LOCK_32
;
436 if (flags
& S1394_CHANNEL_ALLOC_HI
) {
437 IRM_ID_addr
= (IEEE1394_ADDR_BUS_ID_MASK
|
438 IEEE1394_SCSR_CHANS_AVAIL_HI
) |
439 (((uint64_t)IRM_node
) <<
440 IEEE1394_ADDR_PHY_ID_SHIFT
);
442 IRM_ID_addr
= (IEEE1394_ADDR_BUS_ID_MASK
|
443 IEEE1394_SCSR_CHANS_AVAIL_LO
) |
444 (((uint64_t)IRM_node
) <<
445 IEEE1394_ADDR_PHY_ID_SHIFT
);
448 cmd
->cmd_addr
= IRM_ID_addr
;
449 cmd
->bus_generation
= generation
;
450 cmd
->cmd_u
.l32
.data_value
= T1394_DATA32(~channel_mask
);
451 cmd
->cmd_u
.l32
.num_retries
= num_retries
;
452 cmd
->cmd_u
.l32
.lock_type
= CMD1394_LOCK_BIT_AND
;
454 ret
= s1394_split_lock_req(hal
, NULL
, cmd
);
456 if (ret
== DDI_SUCCESS
) {
457 if (cmd
->cmd_result
== CMD1394_CMDSUCCESS
) {
458 *old_channels
= T1394_DATA32(
459 cmd
->cmd_u
.l32
.old_value
);
461 if ((~(*old_channels
) & channel_mask
) != 0) {
462 *result
= CMD1394_ERETRIES_EXCEEDED
;
463 TNF_PROBE_1(s1394_channel_alloc_error
,
464 S1394_TNF_SL_ISOCH_ERROR
, "",
466 "Channels already taken");
468 s1394_channel_alloc_exit
,
469 S1394_TNF_SL_ISOCH_STACK
, "");
472 *result
= cmd
->cmd_result
;
475 /* Need to free the command */
476 (void) s1394_free_cmd(hal
, &cmd
);
478 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit
,
479 S1394_TNF_SL_ISOCH_STACK
, "");
483 *result
= cmd
->cmd_result
;
484 /* Need to free the command */
485 (void) s1394_free_cmd(hal
, &cmd
);
487 TNF_PROBE_1(s1394_channel_alloc_error
,
488 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
489 msg
, "Error allocating isoch channel");
490 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit
,
491 S1394_TNF_SL_ISOCH_STACK
, "");
492 return (DDI_FAILURE
);
495 *result
= cmd
->cmd_result
;
497 /* Need to free the command */
498 (void) s1394_free_cmd(hal
, &cmd
);
500 TNF_PROBE_1(s1394_channel_alloc_error
,
501 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
502 "Error allocating isoch channel");
503 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit
,
504 S1394_TNF_SL_ISOCH_STACK
, "");
505 return (DDI_FAILURE
);
511 * s1394_channel_free()
512 * is used to free up an isochronous channel. A channel mask and
513 * generation are passed. A request is sent to whichever node is the
514 * IRM for the appropriate channels. If it fails because of a bus
515 * reset it can be retried. If it fails for another reason the
516 * channel(s) may already be free or there may be no IRM.
519 s1394_channel_free(s1394_hal_t
*hal
, uint32_t channel_mask
, uint_t generation
,
520 uint_t flags
, uint32_t *old_channels
, int *result
)
523 uint64_t IRM_ID_addr
;
532 int num_retries
= S1394_ISOCH_ALLOC_RETRIES
;
534 TNF_PROBE_0_DEBUG(s1394_channel_free_enter
,
535 S1394_TNF_SL_ISOCH_STACK
, "");
537 /* Lock the topology tree */
538 mutex_enter(&hal
->topology_tree_mutex
);
540 hal_node_num
= IEEE1394_NODE_NUM(hal
->node_id
);
541 IRM_node
= hal
->IRM_node
;
543 /* Unlock the topology tree */
544 mutex_exit(&hal
->topology_tree_mutex
);
546 /* Make sure there is a valid IRM on the bus */
547 if (IRM_node
== -1) {
548 *result
= CMD1394_ERETRIES_EXCEEDED
;
549 TNF_PROBE_1(s1394_channel_free_error
,
550 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
551 "No IRM on the 1394 bus");
552 TNF_PROBE_0_DEBUG(s1394_channel_free_exit
,
553 S1394_TNF_SL_ISOCH_STACK
, "");
554 return (DDI_FAILURE
);
557 if (flags
& S1394_CHANNEL_ALLOC_HI
) {
559 (IEEE1394_SCSR_CHANS_AVAIL_HI
& IEEE1394_CSR_OFFSET_MASK
);
562 (IEEE1394_SCSR_CHANS_AVAIL_LO
& IEEE1394_CSR_OFFSET_MASK
);
565 /* Send compare-swap to CHANNELS_AVAILABLE */
566 /* register on the Isoch Rsrc Mgr */
567 if (hal
->IRM_node
== hal_node_num
) {
571 (void) HAL_CALL(hal
).csr_read(hal
->halinfo
.hal_private
,
574 /* Check that the generation has not changed */
575 if (generation
!= hal
->generation_count
) {
576 *result
= CMD1394_EBUSRESET
;
577 TNF_PROBE_0_DEBUG(s1394_channel_free_exit
,
578 S1394_TNF_SL_ISOCH_STACK
, "");
579 return (DDI_FAILURE
);
583 swap
= old_value
| channel_mask
;
585 ret
= HAL_CALL(hal
).csr_cswap32(
586 hal
->halinfo
.hal_private
, hal
->generation_count
,
587 offset
, compare
, swap
, &old_value
);
588 if (ret
!= DDI_SUCCESS
) {
589 *result
= CMD1394_EBUSRESET
;
590 TNF_PROBE_1(s1394_channel_free_error
,
591 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
592 msg
, "Error in cswap32");
593 TNF_PROBE_0_DEBUG(s1394_channel_free_exit
,
594 "stacktrace 1394 s1394", "");
595 return (DDI_FAILURE
);
598 if (old_value
== compare
) {
599 *result
= CMD1394_CMDSUCCESS
;
600 *old_channels
= old_value
;
601 TNF_PROBE_0_DEBUG(s1394_channel_free_exit
,
602 S1394_TNF_SL_ISOCH_STACK
, "");
603 return (DDI_SUCCESS
);
607 *result
= CMD1394_ERETRIES_EXCEEDED
;
608 TNF_PROBE_1(s1394_channel_free_error
,
609 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
611 TNF_PROBE_0_DEBUG(s1394_channel_free_exit
,
612 S1394_TNF_SL_ISOCH_STACK
, "");
613 return (DDI_FAILURE
);
617 if (s1394_alloc_cmd(hal
, 0, &cmd
) != DDI_SUCCESS
) {
618 *result
= CMD1394_EUNKNOWN_ERROR
;
619 TNF_PROBE_1(s1394_channel_free_error
,
620 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
621 "Unable to allocate command");
622 TNF_PROBE_0_DEBUG(s1394_channel_free_exit
,
623 S1394_TNF_SL_ISOCH_STACK
, "");
624 return (DDI_FAILURE
);
627 cmd
->cmd_options
= (CMD1394_CANCEL_ON_BUS_RESET
|
628 CMD1394_OVERRIDE_ADDR
| CMD1394_BLOCKING
);
629 cmd
->cmd_type
= CMD1394_ASYNCH_LOCK_32
;
631 if (flags
& S1394_CHANNEL_ALLOC_HI
) {
632 IRM_ID_addr
= (IEEE1394_ADDR_BUS_ID_MASK
|
633 IEEE1394_SCSR_CHANS_AVAIL_HI
) |
634 (((uint64_t)IRM_node
) <<
635 IEEE1394_ADDR_PHY_ID_SHIFT
);
637 IRM_ID_addr
= (IEEE1394_ADDR_BUS_ID_MASK
|
638 IEEE1394_SCSR_CHANS_AVAIL_LO
) |
639 (((uint64_t)IRM_node
) <<
640 IEEE1394_ADDR_PHY_ID_SHIFT
);
643 cmd
->cmd_addr
= IRM_ID_addr
;
644 cmd
->bus_generation
= generation
;
645 cmd
->cmd_u
.l32
.data_value
= T1394_DATA32(channel_mask
);
646 cmd
->cmd_u
.l32
.num_retries
= num_retries
;
647 cmd
->cmd_u
.l32
.lock_type
= CMD1394_LOCK_BIT_OR
;
649 ret
= s1394_split_lock_req(hal
, NULL
, cmd
);
651 if (ret
== DDI_SUCCESS
) {
652 if (cmd
->cmd_result
== CMD1394_CMDSUCCESS
) {
654 *old_channels
= T1394_DATA32(
655 cmd
->cmd_u
.l32
.old_value
);
656 *result
= cmd
->cmd_result
;
658 /* Need to free the command */
659 (void) s1394_free_cmd(hal
, &cmd
);
661 TNF_PROBE_0_DEBUG(s1394_channel_free_exit
,
662 S1394_TNF_SL_ISOCH_STACK
, "");
663 return (DDI_SUCCESS
);
666 *result
= cmd
->cmd_result
;
668 /* Need to free the command */
669 (void) s1394_free_cmd(hal
, &cmd
);
671 TNF_PROBE_1(s1394_channel_free_error
,
672 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
673 msg
, "Error freeing isoch channel");
674 TNF_PROBE_0_DEBUG(s1394_channel_free_exit
,
675 S1394_TNF_SL_ISOCH_STACK
, "");
676 return (DDI_FAILURE
);
679 *result
= cmd
->cmd_result
;
680 /* Need to free the command */
681 (void) s1394_free_cmd(hal
, &cmd
);
683 TNF_PROBE_1(s1394_channel_free_error
,
684 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
685 "Error freeing isoch channel");
686 TNF_PROBE_0_DEBUG(s1394_channel_free_exit
,
687 S1394_TNF_SL_ISOCH_STACK
, "");
688 return (DDI_FAILURE
);
694 * s1394_bandwidth_alloc()
695 * is used to allocate isochronous bandwidth. A number of bandwidth
696 * allocation units and a generation are passed. The request is sent
697 * to whichever node is the IRM for this amount of bandwidth. If it
698 * fails because of a bus reset it can be retried. If it fails for
699 * another reason the bandwidth may not be available or there may be
703 s1394_bandwidth_alloc(s1394_hal_t
*hal
, uint32_t bw_alloc_units
,
704 uint_t generation
, int *result
)
707 uint64_t IRM_ID_addr
;
716 int num_retries
= S1394_ISOCH_ALLOC_RETRIES
;
718 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_enter
,
719 S1394_TNF_SL_ISOCH_STACK
, "");
721 /* Lock the topology tree */
722 mutex_enter(&hal
->topology_tree_mutex
);
724 hal_node_num
= IEEE1394_NODE_NUM(hal
->node_id
);
725 IRM_node
= hal
->IRM_node
;
727 /* Unlock the topology tree */
728 mutex_exit(&hal
->topology_tree_mutex
);
730 /* Make sure there is a valid IRM on the bus */
731 if (IRM_node
== -1) {
732 *result
= CMD1394_ERETRIES_EXCEEDED
;
733 TNF_PROBE_1(s1394_bandwidth_alloc_error
,
734 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
735 "No IRM on the 1394 bus");
736 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit
,
737 S1394_TNF_SL_ISOCH_STACK
, "");
738 return (DDI_FAILURE
);
741 /* Send compare-swap to BANDWIDTH_AVAILABLE */
742 /* register on the Isoch Rsrc Mgr */
743 if (IRM_node
== hal_node_num
) {
747 (void) HAL_CALL(hal
).csr_read(hal
->halinfo
.hal_private
,
748 (IEEE1394_SCSR_BANDWIDTH_AVAIL
&
749 IEEE1394_CSR_OFFSET_MASK
), &old_value
);
751 * Check that the generation has not changed -
752 * don't need the lock (read-only)
754 if (generation
!= hal
->generation_count
) {
755 *result
= CMD1394_EBUSRESET
;
756 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit
,
757 S1394_TNF_SL_ISOCH_STACK
, "");
758 return (DDI_FAILURE
);
761 temp_value
= (old_value
- bw_alloc_units
);
762 if ((old_value
>= bw_alloc_units
) &&
763 (temp_value
>= IEEE1394_BANDWIDTH_MIN
)) {
765 swap
= (uint32_t)temp_value
;
767 *result
= CMD1394_ERETRIES_EXCEEDED
;
768 TNF_PROBE_1(s1394_bandwidth_alloc_error
,
769 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
770 msg
, "Retries exceeded");
771 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit
,
772 S1394_TNF_SL_ISOCH_STACK
, "");
773 return (DDI_FAILURE
);
776 ret
= HAL_CALL(hal
).csr_cswap32(
777 hal
->halinfo
.hal_private
, generation
,
778 (IEEE1394_SCSR_BANDWIDTH_AVAIL
&
779 IEEE1394_CSR_OFFSET_MASK
), compare
, swap
,
781 if (ret
!= DDI_SUCCESS
) {
782 *result
= CMD1394_EBUSRESET
;
783 TNF_PROBE_1(s1394_bandwidth_alloc_error
,
784 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
785 msg
, "Error in cswap32");
786 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit
,
787 S1394_TNF_SL_ISOCH_STACK
, "");
788 return (DDI_FAILURE
);
791 if (old_value
== compare
) {
792 *result
= CMD1394_CMDSUCCESS
;
793 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit
,
794 S1394_TNF_SL_ISOCH_STACK
, "");
795 return (DDI_SUCCESS
);
799 *result
= CMD1394_ERETRIES_EXCEEDED
;
800 TNF_PROBE_1(s1394_bandwidth_alloc_error
,
801 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
803 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit
,
804 S1394_TNF_SL_ISOCH_STACK
, "");
805 return (DDI_FAILURE
);
809 if (s1394_alloc_cmd(hal
, 0, &cmd
) != DDI_SUCCESS
) {
810 *result
= CMD1394_EUNKNOWN_ERROR
;
811 TNF_PROBE_1(s1394_bandwidth_alloc_error
,
812 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
813 "Unable to allocate command");
814 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit
,
815 S1394_TNF_SL_ISOCH_STACK
, "");
816 return (DDI_FAILURE
);
819 cmd
->cmd_options
= (CMD1394_CANCEL_ON_BUS_RESET
|
820 CMD1394_OVERRIDE_ADDR
| CMD1394_BLOCKING
);
821 cmd
->cmd_type
= CMD1394_ASYNCH_LOCK_32
;
822 IRM_ID_addr
= (IEEE1394_ADDR_BUS_ID_MASK
|
823 IEEE1394_SCSR_BANDWIDTH_AVAIL
) | (((uint64_t)IRM_node
) <<
824 IEEE1394_ADDR_PHY_ID_SHIFT
);
825 cmd
->cmd_addr
= IRM_ID_addr
;
826 cmd
->bus_generation
= generation
;
827 cmd
->cmd_u
.l32
.arg_value
= 0;
828 cmd
->cmd_u
.l32
.data_value
= bw_alloc_units
;
829 cmd
->cmd_u
.l32
.num_retries
= num_retries
;
830 cmd
->cmd_u
.l32
.lock_type
= CMD1394_LOCK_THRESH_SUBTRACT
;
832 ret
= s1394_split_lock_req(hal
, NULL
, cmd
);
834 if (ret
== DDI_SUCCESS
) {
835 if (cmd
->cmd_result
== CMD1394_CMDSUCCESS
) {
836 *result
= cmd
->cmd_result
;
837 /* Need to free the command */
838 (void) s1394_free_cmd(hal
, &cmd
);
840 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit
,
841 S1394_TNF_SL_ISOCH_STACK
, "");
842 return (DDI_SUCCESS
);
845 *result
= cmd
->cmd_result
;
846 /* Need to free the command */
847 (void) s1394_free_cmd(hal
, &cmd
);
849 TNF_PROBE_1(s1394_bandwidth_alloc_error
,
850 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
851 msg
, "Error allocating isoch bandwidth");
852 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit
,
853 S1394_TNF_SL_ISOCH_STACK
, "");
854 return (DDI_FAILURE
);
857 *result
= cmd
->cmd_result
;
858 /* Need to free the command */
859 (void) s1394_free_cmd(hal
, &cmd
);
861 TNF_PROBE_1(s1394_bandwidth_alloc_error
,
862 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
863 "Error allocating isoch bandwidth");
864 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit
,
865 S1394_TNF_SL_ISOCH_STACK
, "");
866 return (DDI_FAILURE
);
872 * s1394_compute_bw_alloc_units()
873 * is used to compute the number of "bandwidth allocation units" that
874 * are necessary for a given bit rate. It calculates the overhead
875 * necessary for isoch packet headers, bus arbitration, etc. (See
876 * IEEE 1394-1995 Section 8.3.2.3.7 for an explanation of what a
877 * "bandwidth allocation unit" is.
880 s1394_compute_bw_alloc_units(s1394_hal_t
*hal
, uint_t bandwidth
, uint_t speed
)
887 /* Lock the topology tree */
888 mutex_enter(&hal
->topology_tree_mutex
);
890 /* Calculate the 1394 bus diameter */
891 max_hops
= s1394_topology_tree_calculate_diameter(hal
);
893 /* Unlock the topology tree */
894 mutex_exit(&hal
->topology_tree_mutex
);
896 /* Calculate the total bandwidth (including overhead) */
897 total_quads
= (bandwidth
>> 2) + IEEE1394_ISOCH_HDR_QUAD_SZ
;
900 speed_factor
= ISOCH_SPEED_FACTOR_S400
;
903 speed_factor
= ISOCH_SPEED_FACTOR_S200
;
906 speed_factor
= ISOCH_SPEED_FACTOR_S100
;
909 /* See IEC 61883-1 pp. 26-29 for this formula */
910 bau
= (32 * max_hops
) + (total_quads
* speed_factor
);
916 * s1394_bandwidth_free()
917 * is used to free up isochronous bandwidth. A number of bandwidth
918 * allocation units and a generation are passed. The request is sent
919 * to whichever node is the IRM for this amount of bandwidth. If it
920 * fails because of a bus reset it can be retried. If it fails for
921 * another reason the bandwidth may already be freed or there may
925 s1394_bandwidth_free(s1394_hal_t
*hal
, uint32_t bw_alloc_units
,
926 uint_t generation
, int *result
)
929 uint64_t IRM_ID_addr
;
938 int num_retries
= S1394_ISOCH_ALLOC_RETRIES
;
940 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_enter
,
941 S1394_TNF_SL_ISOCH_STACK
, "");
943 /* Lock the topology tree */
944 mutex_enter(&hal
->topology_tree_mutex
);
946 hal_node_num
= IEEE1394_NODE_NUM(hal
->node_id
);
947 IRM_node
= hal
->IRM_node
;
949 /* Unlock the topology tree */
950 mutex_exit(&hal
->topology_tree_mutex
);
952 /* Make sure there is a valid IRM on the bus */
953 if (IRM_node
== -1) {
954 *result
= CMD1394_ERETRIES_EXCEEDED
;
955 TNF_PROBE_1(s1394_bandwidth_free_error
,
956 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
957 "No IRM on the 1394 bus");
958 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit
,
959 S1394_TNF_SL_ISOCH_STACK
, "");
960 return (DDI_FAILURE
);
963 /* Send compare-swap to BANDWIDTH_AVAILABLE */
964 /* register on the Isoch Rsrc Mgr */
965 if (IRM_node
== hal_node_num
) {
968 (void) HAL_CALL(hal
).csr_read(hal
->halinfo
.hal_private
,
969 (IEEE1394_SCSR_BANDWIDTH_AVAIL
&
970 IEEE1394_CSR_OFFSET_MASK
), &old_value
);
972 /* Check that the generation has not changed */
973 if (generation
!= hal
->generation_count
) {
974 *result
= CMD1394_EBUSRESET
;
975 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit
,
976 S1394_TNF_SL_ISOCH_STACK
, "");
977 return (DDI_FAILURE
);
980 temp_value
= (old_value
+ bw_alloc_units
);
981 if ((temp_value
>= old_value
) &&
982 (temp_value
<= IEEE1394_BANDWIDTH_MAX
)) {
986 *result
= CMD1394_ERETRIES_EXCEEDED
;
987 TNF_PROBE_1(s1394_bandwidth_free_error
,
988 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
989 msg
, "Too many retries");
990 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit
,
991 S1394_TNF_SL_ISOCH_STACK
, "");
992 return (DDI_FAILURE
);
995 ret
= HAL_CALL(hal
).csr_cswap32(
996 hal
->halinfo
.hal_private
, generation
,
997 (IEEE1394_SCSR_BANDWIDTH_AVAIL
&
998 IEEE1394_CSR_OFFSET_MASK
), compare
, swap
,
1000 if (ret
!= DDI_SUCCESS
) {
1001 *result
= CMD1394_EBUSRESET
;
1002 TNF_PROBE_1(s1394_bandwidth_free_error
,
1003 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
1004 msg
, "Error in cswap32");
1005 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit
,
1006 S1394_TNF_SL_ISOCH_STACK
, "");
1007 return (DDI_FAILURE
);
1010 if (old_value
== compare
) {
1011 *result
= CMD1394_CMDSUCCESS
;
1012 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit
,
1013 S1394_TNF_SL_ISOCH_STACK
, "");
1014 return (DDI_SUCCESS
);
1018 *result
= CMD1394_ERETRIES_EXCEEDED
;
1019 TNF_PROBE_1(s1394_bandwidth_free_error
,
1020 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
1021 "Retries exceeded");
1022 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit
,
1023 S1394_TNF_SL_ISOCH_STACK
, "");
1024 return (DDI_FAILURE
);
1028 if (s1394_alloc_cmd(hal
, 0, &cmd
) != DDI_SUCCESS
) {
1029 *result
= CMD1394_EUNKNOWN_ERROR
;
1030 TNF_PROBE_1(s1394_bandwidth_free_error
,
1031 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
1032 "Unable to allocate command");
1033 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit
,
1034 S1394_TNF_SL_ISOCH_STACK
, "");
1035 return (DDI_FAILURE
);
1038 cmd
->cmd_options
= (CMD1394_CANCEL_ON_BUS_RESET
|
1039 CMD1394_OVERRIDE_ADDR
| CMD1394_BLOCKING
);
1040 cmd
->cmd_type
= CMD1394_ASYNCH_LOCK_32
;
1041 IRM_ID_addr
= (IEEE1394_ADDR_BUS_ID_MASK
|
1042 IEEE1394_SCSR_BANDWIDTH_AVAIL
) |
1043 (((uint64_t)hal
->IRM_node
) << IEEE1394_ADDR_PHY_ID_SHIFT
);
1044 cmd
->cmd_addr
= IRM_ID_addr
;
1045 cmd
->bus_generation
= generation
;
1046 cmd
->cmd_u
.l32
.arg_value
= IEEE1394_BANDWIDTH_MAX
;
1047 cmd
->cmd_u
.l32
.data_value
= bw_alloc_units
;
1048 cmd
->cmd_u
.l32
.num_retries
= num_retries
;
1049 cmd
->cmd_u
.l32
.lock_type
= CMD1394_LOCK_THRESH_ADD
;
1051 ret
= s1394_split_lock_req(hal
, NULL
, cmd
);
1053 if (ret
== DDI_SUCCESS
) {
1054 if (cmd
->cmd_result
== CMD1394_CMDSUCCESS
) {
1055 *result
= cmd
->cmd_result
;
1057 /* Need to free the command */
1058 (void) s1394_free_cmd(hal
, &cmd
);
1060 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit
,
1061 S1394_TNF_SL_ISOCH_STACK
, "");
1062 return (DDI_SUCCESS
);
1065 *result
= cmd
->cmd_result
;
1066 /* Need to free the command */
1067 (void) s1394_free_cmd(hal
, &cmd
);
1069 TNF_PROBE_1(s1394_bandwidth_free_error
,
1070 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
,
1071 msg
, "Error freeing isoch bandwidth");
1072 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit
,
1073 S1394_TNF_SL_ISOCH_STACK
, "");
1074 return (DDI_FAILURE
);
1077 *result
= cmd
->cmd_result
;
1078 /* Need to free the command */
1079 (void) s1394_free_cmd(hal
, &cmd
);
1081 TNF_PROBE_1(s1394_bandwidth_free_error
,
1082 S1394_TNF_SL_ISOCH_ERROR
, "", tnf_string
, msg
,
1083 "Error freeing isoch bandwidth");
1084 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit
,
1085 S1394_TNF_SL_ISOCH_STACK
, "");
1086 return (DDI_FAILURE
);
1092 * s1394_isoch_cec_list_insert()
1093 * is used to insert an Isoch CEC into a given HAL's list of Isoch CECs.
1096 s1394_isoch_cec_list_insert(s1394_hal_t
*hal
, s1394_isoch_cec_t
*cec
)
1098 s1394_isoch_cec_t
*cec_temp
;
1100 TNF_PROBE_0_DEBUG(s1394_isoch_cec_list_insert_enter
,
1101 S1394_TNF_SL_ISOCH_STACK
, "");
1103 ASSERT(MUTEX_HELD(&hal
->isoch_cec_list_mutex
));
1105 /* Is the Isoch CEC list empty? */
1106 if ((hal
->isoch_cec_list_head
== NULL
) &&
1107 (hal
->isoch_cec_list_tail
== NULL
)) {
1109 hal
->isoch_cec_list_head
= cec
;
1110 hal
->isoch_cec_list_tail
= cec
;
1112 cec
->cec_next
= NULL
;
1113 cec
->cec_prev
= NULL
;
1116 cec
->cec_next
= hal
->isoch_cec_list_head
;
1117 cec
->cec_prev
= NULL
;
1118 cec_temp
= hal
->isoch_cec_list_head
;
1119 cec_temp
->cec_prev
= cec
;
1121 hal
->isoch_cec_list_head
= cec
;
1124 TNF_PROBE_0_DEBUG(s1394_isoch_cec_list_insert_exit
,
1125 S1394_TNF_SL_ISOCH_STACK
, "");
1129 * s1394_isoch_cec_list_remove()
1130 * is used to remove an Isoch CEC from a given HAL's list of Isoch CECs.
1133 s1394_isoch_cec_list_remove(s1394_hal_t
*hal
, s1394_isoch_cec_t
*cec
)
1135 s1394_isoch_cec_t
*prev_cec
;
1136 s1394_isoch_cec_t
*next_cec
;
1138 TNF_PROBE_0_DEBUG(s1394_isoch_cec_list_remove_enter
,
1139 S1394_TNF_SL_ISOCH_STACK
, "");
1141 ASSERT(MUTEX_HELD(&hal
->isoch_cec_list_mutex
));
1143 prev_cec
= cec
->cec_prev
;
1144 next_cec
= cec
->cec_next
;
1145 cec
->cec_prev
= NULL
;
1146 cec
->cec_next
= NULL
;
1148 if (prev_cec
!= NULL
) {
1149 prev_cec
->cec_next
= next_cec
;
1152 if (hal
->isoch_cec_list_head
== cec
)
1153 hal
->isoch_cec_list_head
= next_cec
;
1156 if (next_cec
!= NULL
) {
1157 next_cec
->cec_prev
= prev_cec
;
1160 if (hal
->isoch_cec_list_tail
== cec
)
1161 hal
->isoch_cec_list_tail
= prev_cec
;
1164 TNF_PROBE_0_DEBUG(s1394_isoch_cec_list_remove_exit
,
1165 S1394_TNF_SL_ISOCH_STACK
, "");
1169 * s1394_isoch_cec_member_list_insert()
1170 * is used to insert a new member (target) into the list of members for
1171 * a given Isoch CEC.
1175 s1394_isoch_cec_member_list_insert(s1394_hal_t
*hal
, s1394_isoch_cec_t
*cec
,
1176 s1394_isoch_cec_member_t
*member
)
1178 s1394_isoch_cec_member_t
*member_temp
;
1180 TNF_PROBE_0_DEBUG(s1394_isoch_cec_member_list_insert_enter
,
1181 S1394_TNF_SL_ISOCH_STACK
, "");
1183 ASSERT(MUTEX_HELD(&cec
->isoch_cec_mutex
));
1185 /* Is the Isoch CEC member list empty? */
1186 if ((cec
->cec_member_list_head
== NULL
) &&
1187 (cec
->cec_member_list_tail
== NULL
)) {
1189 cec
->cec_member_list_head
= member
;
1190 cec
->cec_member_list_tail
= member
;
1191 member
->cec_mem_next
= NULL
;
1192 member
->cec_mem_prev
= NULL
;
1194 } else if (member
->cec_mem_options
& T1394_TALKER
) {
1195 /* Put talker at the head of the list */
1196 member
->cec_mem_next
= cec
->cec_member_list_head
;
1197 member
->cec_mem_prev
= NULL
;
1198 member_temp
= cec
->cec_member_list_head
;
1199 member_temp
->cec_mem_prev
= member
;
1200 cec
->cec_member_list_head
= member
;
1203 /* Put listeners at the tail of the list */
1204 member
->cec_mem_prev
= cec
->cec_member_list_tail
;
1205 member
->cec_mem_next
= NULL
;
1206 member_temp
= cec
->cec_member_list_tail
;
1207 member_temp
->cec_mem_next
= member
;
1208 cec
->cec_member_list_tail
= member
;
1211 TNF_PROBE_0_DEBUG(s1394_isoch_cec_member_list_insert_exit
,
1212 S1394_TNF_SL_ISOCH_STACK
, "");
1216 * s1394_isoch_cec_member_list_remove()
1217 * is used to remove a member (target) from the list of members for
1218 * a given Isoch CEC.
1222 s1394_isoch_cec_member_list_remove(s1394_hal_t
*hal
, s1394_isoch_cec_t
*cec
,
1223 s1394_isoch_cec_member_t
*member
)
1225 s1394_isoch_cec_member_t
*prev_member
;
1226 s1394_isoch_cec_member_t
*next_member
;
1228 TNF_PROBE_0_DEBUG(s1394_isoch_cec_member_list_remove_enter
,
1229 S1394_TNF_SL_ISOCH_STACK
, "");
1231 ASSERT(MUTEX_HELD(&cec
->isoch_cec_mutex
));
1233 prev_member
= member
->cec_mem_prev
;
1234 next_member
= member
->cec_mem_next
;
1236 member
->cec_mem_prev
= NULL
;
1237 member
->cec_mem_next
= NULL
;
1239 if (prev_member
!= NULL
) {
1240 prev_member
->cec_mem_next
= next_member
;
1243 if (cec
->cec_member_list_head
== member
)
1244 cec
->cec_member_list_head
= next_member
;
1247 if (next_member
!= NULL
) {
1248 next_member
->cec_mem_prev
= prev_member
;
1251 if (cec
->cec_member_list_tail
== member
)
1252 cec
->cec_member_list_tail
= prev_member
;
1255 TNF_PROBE_0_DEBUG(s1394_isoch_cec_member_list_remove_exit
,
1256 S1394_TNF_SL_ISOCH_STACK
, "");