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

1 // SPDX-License-Identifier: GPL-2.0
8 #include <asm/arch-tegra/ivc.h>
49 * This structure is divided into two-cache aligned parts, the first is only
52 * which is critical to performance and necessary in non-cache coherent
89 uint32_t frame) in tegra_ivc_frame_addr() argument
91 BUG_ON(frame >= ivc->nframes); in tegra_ivc_frame_addr()
94 (ivc->frame_size * frame); in tegra_ivc_frame_addr()
99 uint32_t frame) in tegra_ivc_frame_pointer() argument
101 return (void *)tegra_ivc_frame_addr(ivc, ch, frame); in tegra_ivc_frame_pointer()
106 unsigned frame) in tegra_ivc_invalidate_frame() argument
108 ulong base = tegra_ivc_frame_addr(ivc, h, frame); in tegra_ivc_invalidate_frame()
109 invalidate_dcache_range(base, base + ivc->frame_size); in tegra_ivc_invalidate_frame()
114 unsigned frame) in tegra_ivc_flush_frame() argument
116 ulong base = tegra_ivc_frame_addr(ivc, h, frame); in tegra_ivc_flush_frame()
117 flush_dcache_range(base, base + ivc->frame_size); in tegra_ivc_flush_frame()
128 uint32_t w_count = ACCESS_ONCE(ch->w_count); in tegra_ivc_channel_empty()
129 uint32_t r_count = ACCESS_ONCE(ch->r_count); in tegra_ivc_channel_empty()
132 * Perform an over-full check to prevent denial of service attacks where in tegra_ivc_channel_empty()
135 * expected to check for full or over-full conditions. in tegra_ivc_channel_empty()
141 if (w_count - r_count > ivc->nframes) in tegra_ivc_channel_empty()
152 * capacity also appear full. in tegra_ivc_channel_full()
154 return (ACCESS_ONCE(ch->w_count) - ACCESS_ONCE(ch->r_count)) >= in tegra_ivc_channel_full()
155 ivc->nframes; in tegra_ivc_channel_full()
160 ACCESS_ONCE(ivc->rx_channel->r_count) = in tegra_ivc_advance_rx()
161 ACCESS_ONCE(ivc->rx_channel->r_count) + 1; in tegra_ivc_advance_rx()
163 if (ivc->r_pos == ivc->nframes - 1) in tegra_ivc_advance_rx()
164 ivc->r_pos = 0; in tegra_ivc_advance_rx()
166 ivc->r_pos++; in tegra_ivc_advance_rx()
171 ACCESS_ONCE(ivc->tx_channel->w_count) = in tegra_ivc_advance_tx()
172 ACCESS_ONCE(ivc->tx_channel->w_count) + 1; in tegra_ivc_advance_tx()
174 if (ivc->w_pos == ivc->nframes - 1) in tegra_ivc_advance_tx()
175 ivc->w_pos = 0; in tegra_ivc_advance_tx()
177 ivc->w_pos++; in tegra_ivc_advance_tx()
185 * tx_channel->state is set locally, so it is not synchronized with in tegra_ivc_check_read()
189 * asynchronous transition of rx_channel->state to ivc_state_ack is not in tegra_ivc_check_read()
192 if (ivc->tx_channel->state != ivc_state_established) in tegra_ivc_check_read()
193 return -ECONNRESET; in tegra_ivc_check_read()
199 * or full. in tegra_ivc_check_read()
201 if (!tegra_ivc_channel_empty(ivc, ivc->rx_channel)) in tegra_ivc_check_read()
205 tegra_ivc_invalidate_counter(ivc, ivc->rx_channel, offset); in tegra_ivc_check_read()
206 return tegra_ivc_channel_empty(ivc, ivc->rx_channel) ? -ENOMEM : 0; in tegra_ivc_check_read()
213 if (ivc->tx_channel->state != ivc_state_established) in tegra_ivc_check_write()
214 return -ECONNRESET; in tegra_ivc_check_write()
216 if (!tegra_ivc_channel_full(ivc, ivc->tx_channel)) in tegra_ivc_check_write()
220 tegra_ivc_invalidate_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_check_write()
221 return tegra_ivc_channel_full(ivc, ivc->tx_channel) ? -ENOMEM : 0; in tegra_ivc_check_write()
229 * over-full situation can lead to denial of service attacks. See the in tegra_ivc_channel_avail_count()
231 * special over-full considerations. in tegra_ivc_channel_avail_count()
233 return ACCESS_ONCE(ch->w_count) - ACCESS_ONCE(ch->r_count); in tegra_ivc_channel_avail_count()
236 int tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc, void **frame) in tegra_ivc_read_get_next_frame() argument
248 tegra_ivc_invalidate_frame(ivc, ivc->rx_channel, ivc->r_pos); in tegra_ivc_read_get_next_frame()
249 *frame = tegra_ivc_frame_pointer(ivc, ivc->rx_channel, ivc->r_pos); in tegra_ivc_read_get_next_frame()
261 * have already observed the channel non-empty. This check is just to in tegra_ivc_read_advance()
270 tegra_ivc_flush_counter(ivc, ivc->rx_channel, offset); in tegra_ivc_read_advance()
278 tegra_ivc_invalidate_counter(ivc, ivc->rx_channel, offset); in tegra_ivc_read_advance()
280 if (tegra_ivc_channel_avail_count(ivc, ivc->rx_channel) == in tegra_ivc_read_advance()
281 ivc->nframes - 1) in tegra_ivc_read_advance()
282 ivc->notify(ivc); in tegra_ivc_read_advance()
287 int tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc, void **frame) in tegra_ivc_write_get_next_frame() argument
293 *frame = tegra_ivc_frame_pointer(ivc, ivc->tx_channel, ivc->w_pos); in tegra_ivc_write_get_next_frame()
307 tegra_ivc_flush_frame(ivc, ivc->tx_channel, ivc->w_pos); in tegra_ivc_write_advance()
310 * Order any possible stores to the frame before update of w_pos. in tegra_ivc_write_advance()
316 tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_write_advance()
324 tegra_ivc_invalidate_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_write_advance()
326 if (tegra_ivc_channel_avail_count(ivc, ivc->tx_channel) == 1) in tegra_ivc_write_advance()
327 ivc->notify(ivc); in tegra_ivc_write_advance()
334 * IVC State Transition Table - see tegra_ivc_channel_notified()
338 * ----- ------ -----------------------------------
358 tegra_ivc_invalidate_counter(ivc, ivc->rx_channel, offset); in tegra_ivc_channel_notified()
359 peer_state = ACCESS_ONCE(ivc->rx_channel->state); in tegra_ivc_channel_notified()
373 ivc->tx_channel->w_count = 0; in tegra_ivc_channel_notified()
374 ivc->rx_channel->r_count = 0; in tegra_ivc_channel_notified()
376 ivc->w_pos = 0; in tegra_ivc_channel_notified()
377 ivc->r_pos = 0; in tegra_ivc_channel_notified()
389 ivc->tx_channel->state = ivc_state_ack; in tegra_ivc_channel_notified()
391 tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_channel_notified()
396 ivc->notify(ivc); in tegra_ivc_channel_notified()
397 } else if (ivc->tx_channel->state == ivc_state_sync && in tegra_ivc_channel_notified()
410 ivc->tx_channel->w_count = 0; in tegra_ivc_channel_notified()
411 ivc->rx_channel->r_count = 0; in tegra_ivc_channel_notified()
413 ivc->w_pos = 0; in tegra_ivc_channel_notified()
414 ivc->r_pos = 0; in tegra_ivc_channel_notified()
427 ivc->tx_channel->state = ivc_state_established; in tegra_ivc_channel_notified()
429 tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_channel_notified()
434 ivc->notify(ivc); in tegra_ivc_channel_notified()
435 } else if (ivc->tx_channel->state == ivc_state_ack) { in tegra_ivc_channel_notified()
449 ivc->tx_channel->state = ivc_state_established; in tegra_ivc_channel_notified()
451 tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_channel_notified()
456 ivc->notify(ivc); in tegra_ivc_channel_notified()
466 if (ivc->tx_channel->state != ivc_state_established) in tegra_ivc_channel_notified()
467 return -EAGAIN; in tegra_ivc_channel_notified()
476 ivc->tx_channel->state = ivc_state_sync; in tegra_ivc_channel_reset()
478 tegra_ivc_flush_counter(ivc, ivc->tx_channel, offset); in tegra_ivc_channel_reset()
479 ivc->notify(ivc); in tegra_ivc_channel_reset()
488 (TEGRA_IVC_ALIGN - 1)); in check_ivc_params()
490 (TEGRA_IVC_ALIGN - 1)); in check_ivc_params()
492 (TEGRA_IVC_ALIGN - 1)); in check_ivc_params()
496 return -EINVAL; in check_ivc_params()
503 if ((qbase1 & (TEGRA_IVC_ALIGN - 1)) || in check_ivc_params()
504 (qbase2 & (TEGRA_IVC_ALIGN - 1))) { in check_ivc_params()
506 return -EINVAL; in check_ivc_params()
509 if (frame_size & (TEGRA_IVC_ALIGN - 1)) { in check_ivc_params()
510 pr_err("tegra_ivc: frame size not adequately aligned\n"); in check_ivc_params()
511 return -EINVAL; in check_ivc_params()
516 ret = -EINVAL; in check_ivc_params()
519 ret = -EINVAL; in check_ivc_params()
537 return -EINVAL; in tegra_ivc_init()
543 ivc->rx_channel = (struct tegra_ivc_channel_header *)rx_base; in tegra_ivc_init()
544 ivc->tx_channel = (struct tegra_ivc_channel_header *)tx_base; in tegra_ivc_init()
545 ivc->w_pos = 0; in tegra_ivc_init()
546 ivc->r_pos = 0; in tegra_ivc_init()
547 ivc->nframes = nframes; in tegra_ivc_init()
548 ivc->frame_size = frame_size; in tegra_ivc_init()
549 ivc->notify = notify; in tegra_ivc_init()