aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Markgraf <steve@steve-m.de>2018-10-07 01:44:23 +0200
committerSteve Markgraf <steve@steve-m.de>2018-10-07 01:44:23 +0200
commitdf33203db5007218384e6724748be52a1d4fdb25 (patch)
tree0b116f817a3d9df40ff6c81f2efa1b72cff89291
parent0fb884942679d1246ae41d018764814401fd8c57 (diff)
downloadosmo-fl2k-df33203db5007218384e6724748be52a1d4fdb25.tar.gz
osmo-fl2k-df33203db5007218384e6724748be52a1d4fdb25.tar.bz2
osmo-fl2k-df33203db5007218384e6724748be52a1d4fdb25.zip
lib: Add workaround for Linux usbfs mmap() bug
The Linux Kernel has a bug on ARM/ARM64 systems where the USB CMA memory is incorrectly mapped to userspace, breaking zerocopy. When the Kernel allocates the memory, it clears it with memset(). If the mapping worked correctly, we should have zeroed out buffers, if it doesn't, we get random Kernel memory. We now check for this, and fall back to buffers in userspace if that's the case. Signed-off-by: Steve Markgraf <steve@steve-m.de>
-rw-r--r--src/libosmo-fl2k.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/libosmo-fl2k.c b/src/libosmo-fl2k.c
index 1112539..7748238 100644
--- a/src/libosmo-fl2k.c
+++ b/src/libosmo-fl2k.c
@@ -591,11 +591,26 @@ static int fl2k_alloc_submit_transfers(fl2k_dev_t *dev)
for (i = 0; i < dev->xfer_buf_num; ++i) {
dev->xfer_buf[i] = libusb_dev_mem_alloc(dev->devh, dev->xfer_buf_len);
- if (!dev->xfer_buf[i]) {
+ if (dev->xfer_buf[i]) {
+ /* Check if Kernel usbfs mmap() bug is present: if the
+ * mapping is correct, the buffers point to memory that
+ * was memset to 0 by the Kernel, otherwise, they point
+ * to random memory. We check if the buffers are zeroed
+ * and otherwise fall back to buffers in userspace.
+ */
+ if (dev->xfer_buf[i][0] || memcmp(dev->xfer_buf[i],
+ dev->xfer_buf[i] + 1,
+ dev->xfer_buf_len - 1)) {
+ fprintf(stderr, "Detected Kernel usbfs mmap() "
+ "bug, falling back to buffers "
+ "in userspace\n");
+ dev->use_zerocopy = 0;
+ break;
+ }
+ } else {
fprintf(stderr, "Failed to allocate zero-copy "
"buffer for transfer %d\nFalling "
"back to buffers in userspace\n", i);
-
dev->use_zerocopy = 0;
break;
}