Make cyclic descriptors in bounce buffers work
This commit is contained in:
parent
8f55f23840
commit
735d0a48bb
|
|
@ -185,6 +185,9 @@ impl DmaBounce {
|
||||||
Self::linear_descriptors_for_buffer(window_size, burst_config, |_| {});
|
Self::linear_descriptors_for_buffer(window_size, burst_config, |_| {});
|
||||||
let bounce_src_descs = if cyclic {
|
let bounce_src_descs = if cyclic {
|
||||||
Self::bounce_descriptors_for_buffer_cyclic(
|
Self::bounce_descriptors_for_buffer_cyclic(
|
||||||
|
row_front_porch_bytes,
|
||||||
|
row_width_bytes,
|
||||||
|
window_size_rows,
|
||||||
unsafe {
|
unsafe {
|
||||||
(
|
(
|
||||||
&mut *(bounce_buffer_dst as *mut _),
|
&mut *(bounce_buffer_dst as *mut _),
|
||||||
|
|
@ -260,7 +263,105 @@ impl DmaBounce {
|
||||||
descriptors
|
descriptors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prepare_descriptors_window(
|
||||||
|
bounce_buffer: &mut [u8],
|
||||||
|
descriptors_window: &mut [DmaDescriptor],
|
||||||
|
row_front_porch_bytes: usize,
|
||||||
|
row_width_bytes: usize,
|
||||||
|
window_size_rows: usize,
|
||||||
|
max_chunk_size: usize,
|
||||||
|
descriptors_per_row: usize,
|
||||||
|
descriptors_per_row_front_porch: usize,
|
||||||
|
) {
|
||||||
|
for (row_index_in_window, descriptors_row) in descriptors_window
|
||||||
|
.chunks_mut(descriptors_per_row)
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
// let row_index = row_index_in_window + window_index * window_size_rows;
|
||||||
|
let (descriptors_row_front_porch, descriptors_row_stored) =
|
||||||
|
descriptors_row.split_at_mut(descriptors_per_row_front_porch);
|
||||||
|
|
||||||
|
// Prepare front porch descriptors.
|
||||||
|
{
|
||||||
|
let mut descriptors_it = descriptors_row_front_porch.iter_mut();
|
||||||
|
let mut remaining_front_porch = row_front_porch_bytes;
|
||||||
|
|
||||||
|
while remaining_front_porch > 0 {
|
||||||
|
let desc = descriptors_it.next().unwrap();
|
||||||
|
let chunk_size = core::cmp::min(max_chunk_size, remaining_front_porch);
|
||||||
|
remaining_front_porch -= chunk_size;
|
||||||
|
// Just make it point at a bounce buffer.
|
||||||
|
// It is guaranteed to have enough bytes by `DmaBounce::new`.
|
||||||
|
desc.buffer = bounce_buffer.as_mut_ptr();
|
||||||
|
desc.set_size(chunk_size);
|
||||||
|
desc.set_length(chunk_size);
|
||||||
|
desc.reset_for_tx(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
descriptors_it.next().is_none(),
|
||||||
|
"front porch descriptors must be used up"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
descriptors_row_front_porch
|
||||||
|
.iter()
|
||||||
|
.map(|desc| desc.size())
|
||||||
|
.sum::<usize>(),
|
||||||
|
row_front_porch_bytes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare window descriptors.
|
||||||
|
{
|
||||||
|
let mut remaining_bounce_buffer =
|
||||||
|
&mut bounce_buffer[row_index_in_window * row_width_bytes..][..row_width_bytes];
|
||||||
|
|
||||||
|
// if remaining_bounce_buffer.len() > row_width_bytes {
|
||||||
|
// remaining_bounce_buffer = &mut remaining_bounce_buffer[..row_width_bytes];
|
||||||
|
// }
|
||||||
|
|
||||||
|
for desc in &mut *descriptors_row_stored {
|
||||||
|
let chunk_size = core::cmp::min(max_chunk_size, remaining_bounce_buffer.len());
|
||||||
|
desc.buffer = remaining_bounce_buffer.as_mut_ptr();
|
||||||
|
remaining_bounce_buffer = &mut remaining_bounce_buffer[chunk_size..];
|
||||||
|
desc.set_size(chunk_size);
|
||||||
|
desc.set_length(chunk_size);
|
||||||
|
desc.reset_for_tx(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
remaining_bounce_buffer.is_empty(),
|
||||||
|
"bounce buffer must be used up"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
descriptors_row_stored
|
||||||
|
.iter()
|
||||||
|
.map(|desc| desc.size())
|
||||||
|
.sum::<usize>(),
|
||||||
|
row_width_bytes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set EOF bit on the last descriptor of the window, to signal
|
||||||
|
// that the bounce buffer is done being read from.
|
||||||
|
if let Some(last_desc) = descriptors_window.last_mut() {
|
||||||
|
last_desc.reset_for_tx(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
descriptors_window
|
||||||
|
.iter()
|
||||||
|
.map(|desc| desc.size())
|
||||||
|
.sum::<usize>(),
|
||||||
|
window_size_rows * (row_front_porch_bytes + row_width_bytes)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn bounce_descriptors_for_buffer_cyclic(
|
fn bounce_descriptors_for_buffer_cyclic(
|
||||||
|
row_front_porch_bytes: usize,
|
||||||
|
row_width_bytes: usize,
|
||||||
|
window_size_rows: usize,
|
||||||
bounce_buffers: (&'static mut [u8], &'static mut [u8]),
|
bounce_buffers: (&'static mut [u8], &'static mut [u8]),
|
||||||
burst_config: BurstConfig,
|
burst_config: BurstConfig,
|
||||||
) -> &'static mut [DmaDescriptor] {
|
) -> &'static mut [DmaDescriptor] {
|
||||||
|
|
@ -271,17 +372,23 @@ impl DmaBounce {
|
||||||
);
|
);
|
||||||
|
|
||||||
let buffer_len = bounce_buffers.0.len();
|
let buffer_len = bounce_buffers.0.len();
|
||||||
let max_chunk_size = burst_config.max_compatible_chunk_size();
|
|
||||||
let descriptors_len = dma::descriptor_count(
|
assert_eq!(
|
||||||
buffer_len,
|
buffer_len,
|
||||||
max_chunk_size,
|
row_width_bytes * window_size_rows,
|
||||||
// TODO: This might need to be set to true?
|
"the provided bounce buffers have an invalid size"
|
||||||
// I don't know why cyclic descriptor lists must be at least 3 descriptors long.
|
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let max_chunk_size = burst_config.max_compatible_chunk_size();
|
||||||
|
let descriptors_per_row_front_porch =
|
||||||
|
dma::descriptor_count(row_front_porch_bytes, max_chunk_size, false);
|
||||||
|
let descriptors_per_row_stored =
|
||||||
|
dma::descriptor_count(row_width_bytes, max_chunk_size, false);
|
||||||
|
let descriptors_per_row = descriptors_per_row_stored + descriptors_per_row_front_porch;
|
||||||
|
let descriptors_per_window = window_size_rows * descriptors_per_row;
|
||||||
let descriptors_combined =
|
let descriptors_combined =
|
||||||
Box::leak(vec![DmaDescriptor::EMPTY; 2 * descriptors_len].into_boxed_slice());
|
Box::leak(vec![DmaDescriptor::EMPTY; 2 * descriptors_per_window].into_boxed_slice());
|
||||||
let descriptors_pair = descriptors_combined.split_at_mut(descriptors_len);
|
let descriptors_pair = descriptors_combined.split_at_mut(descriptors_per_window);
|
||||||
|
|
||||||
// Link up the descriptors.
|
// Link up the descriptors.
|
||||||
fn link_up_descriptors(
|
fn link_up_descriptors(
|
||||||
|
|
@ -303,19 +410,16 @@ impl DmaBounce {
|
||||||
(bounce_buffers.0, descriptors_pair.0),
|
(bounce_buffers.0, descriptors_pair.0),
|
||||||
(bounce_buffers.1, descriptors_pair.1),
|
(bounce_buffers.1, descriptors_pair.1),
|
||||||
] {
|
] {
|
||||||
let mut descriptors_it = descriptors.iter_mut();
|
Self::prepare_descriptors_window(
|
||||||
let mut remaining_bounce_buffer = bounce_buffer;
|
bounce_buffer,
|
||||||
|
descriptors,
|
||||||
while !remaining_bounce_buffer.is_empty() {
|
row_front_porch_bytes,
|
||||||
let chunk_size = core::cmp::min(max_chunk_size, remaining_bounce_buffer.len());
|
row_width_bytes,
|
||||||
let desc = descriptors_it.next().unwrap();
|
window_size_rows,
|
||||||
desc.buffer = remaining_bounce_buffer.as_mut_ptr();
|
max_chunk_size,
|
||||||
remaining_bounce_buffer = &mut remaining_bounce_buffer[chunk_size..];
|
descriptors_per_row,
|
||||||
let is_last = remaining_bounce_buffer.is_empty();
|
descriptors_per_row_front_porch,
|
||||||
desc.set_size(chunk_size);
|
);
|
||||||
desc.set_length(chunk_size);
|
|
||||||
desc.reset_for_tx(is_last);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptors_combined
|
descriptors_combined
|
||||||
|
|
@ -345,10 +449,6 @@ impl DmaBounce {
|
||||||
"the provided bounce buffers have an invalid size"
|
"the provided bounce buffers have an invalid size"
|
||||||
);
|
);
|
||||||
|
|
||||||
warn!(
|
|
||||||
"windows_len: {windows_len}\nrow_front_porch_bytes: {row_front_porch_bytes}\nrow_width_bytes: {row_width_bytes}\nwindow_size_rows: {window_size_rows}\nbuffer_len: {buffer_len}",
|
|
||||||
);
|
|
||||||
|
|
||||||
let max_chunk_size = burst_config.max_compatible_chunk_size();
|
let max_chunk_size = burst_config.max_compatible_chunk_size();
|
||||||
let descriptors_per_row_front_porch =
|
let descriptors_per_row_front_porch =
|
||||||
dma::descriptor_count(row_front_porch_bytes, max_chunk_size, false);
|
dma::descriptor_count(row_front_porch_bytes, max_chunk_size, false);
|
||||||
|
|
@ -376,92 +476,16 @@ impl DmaBounce {
|
||||||
{
|
{
|
||||||
let bounce_buffer_index = window_index % 2;
|
let bounce_buffer_index = window_index % 2;
|
||||||
let bounce_buffer = &mut *bounce_buffers[bounce_buffer_index];
|
let bounce_buffer = &mut *bounce_buffers[bounce_buffer_index];
|
||||||
// let bounce_buffer_ptr = bounce_buffers[bounce_buffer_index].as_mut_ptr();
|
|
||||||
// let mut remaining_bounce_buffer = &mut *bounce_buffers[bounce_buffer_index];
|
|
||||||
|
|
||||||
for (row_index_in_window, descriptors_row) in descriptors_window
|
Self::prepare_descriptors_window(
|
||||||
.chunks_mut(descriptors_per_row)
|
bounce_buffer,
|
||||||
.enumerate()
|
descriptors_window,
|
||||||
{
|
row_front_porch_bytes,
|
||||||
// let row_index = row_index_in_window + window_index * window_size_rows;
|
row_width_bytes,
|
||||||
let (descriptors_row_front_porch, descriptors_row_stored) =
|
window_size_rows,
|
||||||
descriptors_row.split_at_mut(descriptors_per_row_front_porch);
|
max_chunk_size,
|
||||||
|
descriptors_per_row,
|
||||||
// Prepare front porch descriptors.
|
descriptors_per_row_front_porch,
|
||||||
{
|
|
||||||
let mut descriptors_it = descriptors_row_front_porch.iter_mut();
|
|
||||||
let mut remaining_front_porch = row_front_porch_bytes;
|
|
||||||
|
|
||||||
while remaining_front_porch > 0 {
|
|
||||||
let desc = descriptors_it.next().unwrap();
|
|
||||||
let chunk_size = core::cmp::min(max_chunk_size, remaining_front_porch);
|
|
||||||
remaining_front_porch -= chunk_size;
|
|
||||||
// Just make it point at a bounce buffer.
|
|
||||||
// It is guaranteed to have enough bytes by `DmaBounce::new`.
|
|
||||||
desc.buffer = bounce_buffer.as_mut_ptr();
|
|
||||||
desc.set_size(chunk_size);
|
|
||||||
desc.set_length(chunk_size);
|
|
||||||
desc.reset_for_tx(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
descriptors_it.next().is_none(),
|
|
||||||
"front porch descriptors must be used up"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
descriptors_row_front_porch
|
|
||||||
.iter()
|
|
||||||
.map(|desc| desc.size())
|
|
||||||
.sum::<usize>(),
|
|
||||||
row_front_porch_bytes
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare window descriptors.
|
|
||||||
{
|
|
||||||
let mut remaining_bounce_buffer = &mut bounce_buffer
|
|
||||||
[row_index_in_window * row_width_bytes..][..row_width_bytes];
|
|
||||||
|
|
||||||
// if remaining_bounce_buffer.len() > row_width_bytes {
|
|
||||||
// remaining_bounce_buffer = &mut remaining_bounce_buffer[..row_width_bytes];
|
|
||||||
// }
|
|
||||||
|
|
||||||
for desc in &mut *descriptors_row_stored {
|
|
||||||
let chunk_size =
|
|
||||||
core::cmp::min(max_chunk_size, remaining_bounce_buffer.len());
|
|
||||||
desc.buffer = remaining_bounce_buffer.as_mut_ptr();
|
|
||||||
remaining_bounce_buffer = &mut remaining_bounce_buffer[chunk_size..];
|
|
||||||
desc.set_size(chunk_size);
|
|
||||||
desc.set_length(chunk_size);
|
|
||||||
desc.reset_for_tx(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
remaining_bounce_buffer.is_empty(),
|
|
||||||
"bounce buffer must be used up"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
descriptors_row_stored
|
|
||||||
.iter()
|
|
||||||
.map(|desc| desc.size())
|
|
||||||
.sum::<usize>(),
|
|
||||||
row_width_bytes
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set EOF bit on the last descriptor of the window, to signal
|
|
||||||
// that the bounce buffer is done being read from.
|
|
||||||
if let Some(last_desc) = descriptors_window.last_mut() {
|
|
||||||
last_desc.reset_for_tx(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
descriptors_window
|
|
||||||
.iter()
|
|
||||||
.map(|desc| desc.size())
|
|
||||||
.sum::<usize>(),
|
|
||||||
window_size_rows * (row_front_porch_bytes + row_width_bytes)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue