Lines Matching +full:full +full:- +full:frame

4  * SPDX-License-Identifier: GPL-2.0
9 #include <asm/arch-tegra/ivc.h>
50 * This structure is divided into two-cache aligned parts, the first is only
53 * which is critical to performance and necessary in non-cache coherent
90 uint32_t frame) in tegra_ivc_frame_addr() argument
92 BUG_ON(frame >= ivc->nframes); in tegra_ivc_frame_addr()
95 (ivc->frame_size * frame); in tegra_ivc_frame_addr()
100 uint32_t frame) in tegra_ivc_frame_pointer() argument
102 return (void *)tegra_ivc_frame_addr(ivc, ch, frame); in tegra_ivc_frame_pointer()
107 unsigned frame) in tegra_ivc_invalidate_frame() argument
109 ulong base = tegra_ivc_frame_addr(ivc, h, frame); in tegra_ivc_invalidate_frame()
110 invalidate_dcache_range(base, base + ivc->frame_size); in tegra_ivc_invalidate_frame()
115 unsigned frame) in tegra_ivc_flush_frame() argument
117 ulong base = tegra_ivc_frame_addr(ivc, h, frame); in tegra_ivc_flush_frame()
118 flush_dcache_range(base, base + ivc->frame_size); in tegra_ivc_flush_frame()
129 uint32_t w_count = ACCESS_ONCE(ch->w_count); in tegra_ivc_channel_empty()
130 uint32_t r_count = ACCESS_ONCE(ch->r_count); in tegra_ivc_channel_empty()
133 * Perform an over-full check to prevent denial of service attacks where in tegra_ivc_channel_empty()
136 * expected to check for full or over-full conditions. in tegra_ivc_channel_empty()
142 if (w_count - r_count > ivc->nframes) in tegra_ivc_channel_empty()
153 * capacity also appear full. in tegra_ivc_channel_full()
155 return (ACCESS_ONCE(ch->w_count) - ACCESS_ONCE(ch->r_count)) >= in tegra_ivc_channel_full()
156 ivc->nframes; in tegra_ivc_channel_full()
161 ACCESS_ONCE(ivc->rx_channel->r_count) = in tegra_ivc_advance_rx()
162 ACCESS_ONCE(ivc->rx_channel->r_count) + 1; in tegra_ivc_advance_rx()
164 if (ivc->r_pos == ivc->nframes - 1) in tegra_ivc_advance_rx()
165 ivc->r_pos = 0; in tegra_ivc_advance_rx()
167 ivc->r_pos++; in tegra_ivc_advance_rx()
172 ACCESS_ONCE(ivc->tx_channel->w_count) = in tegra_ivc_advance_tx()
173 ACCESS_ONCE(ivc->tx_channel->w_count) + 1; in tegra_ivc_advance_tx()
175 if (ivc->w_pos == ivc->nframes - 1) in tegra_ivc_advance_tx()
176 ivc->w_pos = 0; in tegra_ivc_advance_tx()
178 ivc->w_pos++; in tegra_ivc_advance_tx()
186 * tx_channel->state is set locally, so it is not synchronized with in tegra_ivc_check_read()
190 * asynchronous transition of rx_channel->state to ivc_state_ack is not in tegra_ivc_check_read()
193 if (ivc->tx_channel->state != ivc_state_established) in tegra_ivc_check_read()
194 return -ECONNRESET; in tegra_ivc_check_read()
200 * or full. in tegra_ivc_check_read()
202 if (!tegra_ivc_channel_empty(ivc, ivc->rx_channel)) in tegra_ivc_check_read()
206 tegra_ivc_invalidate_counter(ivc, ivc->rx_channel, offset); in tegra_ivc_check_read()
207 return tegra_ivc_channel_empty(ivc, ivc->rx_channel) ? -ENOMEM : 0; in tegra_ivc_check_read()
214 if (ivc->tx_channel->state != ivc_state_established) in tegra_ivc_check_write()
215 return -ECONNRESET; in tegra_ivc_check_write()
217 if (!tegra_ivc_channel_full(ivc, ivc->tx_channel)) in tegra_ivc_check_write()
221 tegra_ivc_invalidate_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_check_write()
222 return tegra_ivc_channel_full(ivc, ivc->tx_channel) ? -ENOMEM : 0; in tegra_ivc_check_write()
230 * over-full situation can lead to denial of service attacks. See the in tegra_ivc_channel_avail_count()
232 * special over-full considerations. in tegra_ivc_channel_avail_count()
234 return ACCESS_ONCE(ch->w_count) - ACCESS_ONCE(ch->r_count); in tegra_ivc_channel_avail_count()
237 int tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc, void **frame) in tegra_ivc_read_get_next_frame() argument
249 tegra_ivc_invalidate_frame(ivc, ivc->rx_channel, ivc->r_pos); in tegra_ivc_read_get_next_frame()
250 *frame = tegra_ivc_frame_pointer(ivc, ivc->rx_channel, ivc->r_pos); in tegra_ivc_read_get_next_frame()
262 * have already observed the channel non-empty. This check is just to in tegra_ivc_read_advance()
271 tegra_ivc_flush_counter(ivc, ivc->rx_channel, offset); in tegra_ivc_read_advance()
279 tegra_ivc_invalidate_counter(ivc, ivc->rx_channel, offset); in tegra_ivc_read_advance()
281 if (tegra_ivc_channel_avail_count(ivc, ivc->rx_channel) == in tegra_ivc_read_advance()
282 ivc->nframes - 1) in tegra_ivc_read_advance()
283 ivc->notify(ivc); in tegra_ivc_read_advance()
288 int tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc, void **frame) in tegra_ivc_write_get_next_frame() argument
294 *frame = tegra_ivc_frame_pointer(ivc, ivc->tx_channel, ivc->w_pos); in tegra_ivc_write_get_next_frame()
308 tegra_ivc_flush_frame(ivc, ivc->tx_channel, ivc->w_pos); in tegra_ivc_write_advance()
311 * Order any possible stores to the frame before update of w_pos. in tegra_ivc_write_advance()
317 tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_write_advance()
325 tegra_ivc_invalidate_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_write_advance()
327 if (tegra_ivc_channel_avail_count(ivc, ivc->tx_channel) == 1) in tegra_ivc_write_advance()
328 ivc->notify(ivc); in tegra_ivc_write_advance()
335 * IVC State Transition Table - see tegra_ivc_channel_notified()
339 * ----- ------ -----------------------------------
359 tegra_ivc_invalidate_counter(ivc, ivc->rx_channel, offset); in tegra_ivc_channel_notified()
360 peer_state = ACCESS_ONCE(ivc->rx_channel->state); in tegra_ivc_channel_notified()
374 ivc->tx_channel->w_count = 0; in tegra_ivc_channel_notified()
375 ivc->rx_channel->r_count = 0; in tegra_ivc_channel_notified()
377 ivc->w_pos = 0; in tegra_ivc_channel_notified()
378 ivc->r_pos = 0; in tegra_ivc_channel_notified()
390 ivc->tx_channel->state = ivc_state_ack; in tegra_ivc_channel_notified()
392 tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_channel_notified()
397 ivc->notify(ivc); in tegra_ivc_channel_notified()
398 } else if (ivc->tx_channel->state == ivc_state_sync && in tegra_ivc_channel_notified()
411 ivc->tx_channel->w_count = 0; in tegra_ivc_channel_notified()
412 ivc->rx_channel->r_count = 0; in tegra_ivc_channel_notified()
414 ivc->w_pos = 0; in tegra_ivc_channel_notified()
415 ivc->r_pos = 0; in tegra_ivc_channel_notified()
428 ivc->tx_channel->state = ivc_state_established; in tegra_ivc_channel_notified()
430 tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_channel_notified()
435 ivc->notify(ivc); in tegra_ivc_channel_notified()
436 } else if (ivc->tx_channel->state == ivc_state_ack) { in tegra_ivc_channel_notified()
450 ivc->tx_channel->state = ivc_state_established; in tegra_ivc_channel_notified()
452 tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_channel_notified()
457 ivc->notify(ivc); in tegra_ivc_channel_notified()
467 if (ivc->tx_channel->state != ivc_state_established) in tegra_ivc_channel_notified()
468 return -EAGAIN; in tegra_ivc_channel_notified()
477 ivc->tx_channel->state = ivc_state_sync; in tegra_ivc_channel_reset()
479 tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_channel_reset()
480 ivc->notify(ivc); in tegra_ivc_channel_reset()
489 (TEGRA_IVC_ALIGN - 1)); in check_ivc_params()
491 (TEGRA_IVC_ALIGN - 1)); in check_ivc_params()
493 (TEGRA_IVC_ALIGN - 1)); in check_ivc_params()
497 return -EINVAL; in check_ivc_params()
504 if ((qbase1 & (TEGRA_IVC_ALIGN - 1)) || in check_ivc_params()
505 (qbase2 & (TEGRA_IVC_ALIGN - 1))) { in check_ivc_params()
507 return -EINVAL; in check_ivc_params()
510 if (frame_size & (TEGRA_IVC_ALIGN - 1)) { in check_ivc_params()
511 pr_err("tegra_ivc: frame size not adequately aligned\n"); in check_ivc_params()
512 return -EINVAL; in check_ivc_params()
517 ret = -EINVAL; in check_ivc_params()
520 ret = -EINVAL; in check_ivc_params()
538 return -EINVAL; in tegra_ivc_init()
544 ivc->rx_channel = (struct tegra_ivc_channel_header *)rx_base; in tegra_ivc_init()
545 ivc->tx_channel = (struct tegra_ivc_channel_header *)tx_base; in tegra_ivc_init()
546 ivc->w_pos = 0; in tegra_ivc_init()
547 ivc->r_pos = 0; in tegra_ivc_init()
548 ivc->nframes = nframes; in tegra_ivc_init()
549 ivc->frame_size = frame_size; in tegra_ivc_init()
550 ivc->notify = notify; in tegra_ivc_init()