Skip to content

Conversation

@hugolm84
Copy link

@hugolm84 hugolm84 commented Mar 1, 2022

The SPI driver should, if possible, use as large buffer as possible. Currently, only xfer3 is adhering to the requested max blk size specified in /sys/module/spidev/parameters/bufsiz but is sending it in chunks. For all other xfer functions, the block size is limited to 4096.

I believe that xfer3 was introduced to fix this, however, it is still limited to 4096 chunks.

This PR aims to clarify xfer3 behavior and allow for arbitrary xfer buffer size.

@fschrempf fschrempf self-requested a review September 27, 2025 08:23
@fschrempf
Copy link
Collaborator

fschrempf commented Sep 27, 2025

Rebased to current master

Copy link
Collaborator

@fschrempf fschrempf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hugolm84 Thanks for your work! As it has been a while, are you somehow still interested in working on this PR or rather not?

PyObject *obj;
PyObject *seq;
const uint32_t spi_blk_maxsize = get_xfer_block_size();
uint8_t buf[spi_blk_maxsize];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you are using a VLA (variable length array) here. While this might be supported and probably works, it is something that a lot of people think is bad practice for various reasons. I think one of the following options might be more suited:

  1. Use dynamic buffer allocation
  2. Use a static buffer with size XFER_MAX_BLOCK_SIZE as we don't need to care too much about saving memory

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right about VLAs—this does drop C89 support.

My goals were to:

  • avoid oversized fixed stack buffers while keeping portability,
  • avoid malloc/free in the I/O hot path (too slow on Raspberry Pi ↔ SoC transfers).

With a capped VLA:

  • stack use matches the actual need (typically <4KB, max 65KB),
  • growth is safely bounded,
  • no malloc overhead, best performance.

If strict C89 compliance is required, VLA needs to be addressed, but IIRC it's not possible to just request XFER_MAX_BLOCK_SIZE of stack on some devices.

Copy link
Collaborator

@fschrempf fschrempf Sep 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good points!

but IIRC it's not possible to just request XFER_MAX_BLOCK_SIZE of stack on some devices.

I can't really judge that. I thought it would be safe to allocate a 64 KiB array on the stack on any Linux system, but that might be wrong. If we think it is not safe to do so we should probably avoid this case altogether. No matter if it is caused by a fixed stack buffer or through a VLA that can potentially have the same size.

avoid malloc/free in the I/O hot path (too slow on Raspberry Pi ↔ SoC transfers).

Same here, I can't really judge if the malloc in the hot path would impact the performance in practice. The xfer functions already use dynamic buffers for RX and TX. But I agree that avoiding it would be nice.

What about using a buffer on the heap that is tied to the lifetime of the spidev Python object? This buffer could then later be used by all transfer functions (writebytes, xfer, etc.)? This would result in:

  • no malloc overhead in hot path
  • no risk of hitting any stack limits
  • no C89 compliance issues (if this is a problem at all)
  • no problems due to VLAs apparently being optional in C11 and therefore not having a guarantee that compilers will support them in the future

PyObject *seq;
const uint32_t spi_blk_maxsize = get_xfer_block_size();
uint8_t buf[spi_blk_maxsize];
char wrmsg_text[spi_blk_maxsize];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the message string buffer have the same size as the data buffer? This looks wrong.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you are correct. Previously it was set to 4096, which come to think about it, might be a bit over sized. Perhaps

#define ERR_MSG_SIZE 256
char wrmsg_text[ERR_MSG_SIZE];

is enough?

@hugolm84
Copy link
Author

@hugolm84 Thanks for your work! As it has been a while, are you somehow still interested in working on this PR or rather not?

HI @fschrempf Thanks for taking a look at this. It was a few years ago I made this, and the reason was some performance issues I had between the host and device.
I am not working with that project anymore and might have some issues setting it up again. So, I cannot verify / test this anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants