genio: u-boot: patch: UFS 4k UMS fixes + BTRFS fixes/enablement
- backport fixes from upstream u-boot for
- BTRFS (plus enable BTRFS and BZIP2 support for radxa-nio-12l)
- tested with `CARD_DEVICE=/dev/mmcblk1 ROOTFS_TYPE=btrfs BTRFS_COMPRESSION=zstd` (no UFS!)
- also with `EXT=ufs CARD_DEVICE=/dev/sdc ROOTFS_TYPE=btrfs BTRFS_COMPRESSION=zstd` (UFS!)
- 4k block size UFS for UMS: fixes block size issue (USB issues unhandled)
- Enable "bind" command for the Mediatek-standard USB Gadget Ethernet
This commit is contained in:
parent
872863b95a
commit
324d1ed403
@ -0,0 +1,56 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ricardo Pardini <ricardo@pardini.net>
|
||||
Date: Sat, 3 Jan 2026 21:06:01 +0100
|
||||
Subject: GENIO: radxa-nio-12l: Enable bind command
|
||||
|
||||
After commit 9bc199d7ea5 ("GENIO: board: 350/510/700/1200 EVK: Drop
|
||||
deprecated usb_ether_init()") USB Ethernet Gadget needs to be manually
|
||||
binded using the `bind` command. Let's enable that on Radxa NIO-12L.
|
||||
|
||||
Fixes: 8d921703e1fc5b446b041a7c81e93ca0455d573c # when nio-12l did not exist yet
|
||||
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
|
||||
---
|
||||
configs/genio_1200_radxa_nio_12l_d16_defconfig | 1 +
|
||||
configs/genio_1200_radxa_nio_12l_d4_defconfig | 1 +
|
||||
configs/genio_1200_radxa_nio_12l_d8_defconfig | 1 +
|
||||
3 files changed, 3 insertions(+)
|
||||
|
||||
diff --git a/configs/genio_1200_radxa_nio_12l_d16_defconfig b/configs/genio_1200_radxa_nio_12l_d16_defconfig
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/configs/genio_1200_radxa_nio_12l_d16_defconfig
|
||||
+++ b/configs/genio_1200_radxa_nio_12l_d16_defconfig
|
||||
@@ -36,6 +36,7 @@ CONFIG_CMD_NVEDIT_EFI=y
|
||||
CONFIG_CMD_NVEDIT_INFO=y
|
||||
# CONFIG_CMD_CRC32 is not set
|
||||
CONFIG_CMD_ADC=y
|
||||
+CONFIG_CMD_BIND=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_DFU=y
|
||||
CONFIG_CMD_DM=y
|
||||
diff --git a/configs/genio_1200_radxa_nio_12l_d4_defconfig b/configs/genio_1200_radxa_nio_12l_d4_defconfig
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/configs/genio_1200_radxa_nio_12l_d4_defconfig
|
||||
+++ b/configs/genio_1200_radxa_nio_12l_d4_defconfig
|
||||
@@ -36,6 +36,7 @@ CONFIG_CMD_NVEDIT_EFI=y
|
||||
CONFIG_CMD_NVEDIT_INFO=y
|
||||
# CONFIG_CMD_CRC32 is not set
|
||||
CONFIG_CMD_ADC=y
|
||||
+CONFIG_CMD_BIND=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_DFU=y
|
||||
CONFIG_CMD_DM=y
|
||||
diff --git a/configs/genio_1200_radxa_nio_12l_d8_defconfig b/configs/genio_1200_radxa_nio_12l_d8_defconfig
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/configs/genio_1200_radxa_nio_12l_d8_defconfig
|
||||
+++ b/configs/genio_1200_radxa_nio_12l_d8_defconfig
|
||||
@@ -36,6 +36,7 @@ CONFIG_CMD_NVEDIT_EFI=y
|
||||
CONFIG_CMD_NVEDIT_INFO=y
|
||||
# CONFIG_CMD_CRC32 is not set
|
||||
CONFIG_CMD_ADC=y
|
||||
+CONFIG_CMD_BIND=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_DFU=y
|
||||
CONFIG_CMD_DM=y
|
||||
--
|
||||
Armbian
|
||||
|
||||
@ -0,0 +1,545 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Rini <trini@konsulko.com>
|
||||
Date: Wed, 5 Apr 2023 19:48:57 -0400
|
||||
Subject: UPSTREAM: usb: gadget: UMS: support multiple sector sizes (plus three
|
||||
others)
|
||||
|
||||
--> rpardini: this indeed fixes UFS support for UMS. Unfortunately,
|
||||
it seems there's still trouble with USB/OTG impl
|
||||
itself on Mediatek; UMS doesn't really work either
|
||||
with MMC or with UFS. Still, this would be needed
|
||||
when the USB stuff is hopefully fixed.
|
||||
|
||||
--> rpardini: This cherry-picks and squashes upstream revisions:
|
||||
---> 73b39a76e34a3b88a7a2c58588c9a5a604a51d90
|
||||
|
||||
usb: gadget: f_mass_storage: Rework do_request_sense slightly
|
||||
|
||||
When building with clang, it notes that sdinfo may be unused
|
||||
uninitialized in some cases. This appears to be true from reading the
|
||||
code, and we can simply set the variable to zero to start with and be as
|
||||
correct as before.
|
||||
|
||||
Signed-off-by: Tom Rini <trini@konsulko.com>
|
||||
Reviewed-by: Marek Vasut <marex@denx.de>
|
||||
|
||||
---> f032260c7c336cf88c1914286fd42a1588080db3
|
||||
|
||||
cmd: ums: Use plain udevice for UDC controller interaction
|
||||
|
||||
Convert to plain udevice interaction with UDC controller
|
||||
device, avoid the use of UDC uclass dev_array .
|
||||
|
||||
Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
|
||||
Tested-by: Mattijs Korpershoek <mkorpershoek@baylibre.com> # on khadas vim3
|
||||
Signed-off-by: Marek Vasut <marex@denx.de>
|
||||
|
||||
---> 1041ee64eb18f7a3af30085765ced149cb4dc7cf
|
||||
|
||||
usb: gadget: f_mass_storage: Stop ums on START-STOP UNIT SCSI command
|
||||
|
||||
Exit the UMS handler loop in case START-STOP UNIT SCSI command is
|
||||
received. This is sent e.g. by the util-linux eject(1) command and
|
||||
indicates to the device that it is supposed to spin down the media
|
||||
and enter low power state.
|
||||
|
||||
This effectively adds support for exitting the 'ums' command from
|
||||
host using 'eject /dev/sdN' that is on par with 'dfu-util -e' .
|
||||
|
||||
Signed-off-by: Marek Vasut <marex@denx.de>
|
||||
Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
|
||||
Link: https://lore.kernel.org/r/20231107001018.55640-1-marex@denx.de
|
||||
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
|
||||
|
||||
---> 304fa0aa445384e5e681a54abf413850591cec10
|
||||
|
||||
usb: gadget: UMS: support multiple sector sizes
|
||||
|
||||
UFS storage often uses a 4096-byte sector size, add support for dynamic
|
||||
sector sizes based loosely on the Linux implementation.
|
||||
|
||||
Support for dynamic sector sizes changes the types used in some
|
||||
divisions, resulting in the compiler attempting to use
|
||||
libgcc helpers (__aeabi_ldivmod).
|
||||
Replace these divisions with calls to lldiv() to handle this correctly.
|
||||
|
||||
Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
|
||||
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
|
||||
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20240320-b4-qcom-usb-v4-4-41be480172e1@linaro.org
|
||||
[mkorpershoek: squashed the lldiv() fix from caleb]
|
||||
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
|
||||
---
|
||||
cmd/usb_mass_storage.c | 14 +-
|
||||
drivers/usb/gadget/f_mass_storage.c | 120 ++++++----
|
||||
drivers/usb/gadget/storage_common.c | 12 +-
|
||||
include/usb_mass_storage.h | 3 +-
|
||||
4 files changed, 85 insertions(+), 64 deletions(-)
|
||||
|
||||
diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/cmd/usb_mass_storage.c
|
||||
+++ b/cmd/usb_mass_storage.c
|
||||
@@ -87,10 +87,6 @@ static int ums_init(const char *devtype, const char *devnums_part_str)
|
||||
if (!strchr(devnum_part_str, ':'))
|
||||
partnum = 0;
|
||||
|
||||
- /* f_mass_storage.c assumes SECTOR_SIZE sectors */
|
||||
- if (block_dev->blksz != SECTOR_SIZE)
|
||||
- goto cleanup;
|
||||
-
|
||||
ums_new = realloc(ums, (ums_count + 1) * sizeof(*ums));
|
||||
if (!ums_new)
|
||||
goto cleanup;
|
||||
@@ -143,6 +139,7 @@ static int do_usb_mass_storage(struct cmd_tbl *cmdtp, int flag,
|
||||
const char *devtype;
|
||||
const char *devnum;
|
||||
unsigned int controller_index;
|
||||
+ struct udevice *udc;
|
||||
int rc;
|
||||
int cable_ready_timeout __maybe_unused;
|
||||
|
||||
@@ -164,13 +161,14 @@ static int do_usb_mass_storage(struct cmd_tbl *cmdtp, int flag,
|
||||
|
||||
controller_index = (unsigned int)(simple_strtoul(
|
||||
usb_controller, NULL, 0));
|
||||
- if (usb_gadget_initialize(controller_index)) {
|
||||
+ rc = udc_device_get_by_index(controller_index, &udc);
|
||||
+ if (rc) {
|
||||
pr_err("Couldn't init USB controller.\n");
|
||||
rc = CMD_RET_FAILURE;
|
||||
goto cleanup_ums_init;
|
||||
}
|
||||
|
||||
- rc = fsg_init(ums, ums_count, controller_index);
|
||||
+ rc = fsg_init(ums, ums_count, udc);
|
||||
if (rc) {
|
||||
pr_err("fsg_init failed\n");
|
||||
rc = CMD_RET_FAILURE;
|
||||
@@ -215,7 +213,7 @@ static int do_usb_mass_storage(struct cmd_tbl *cmdtp, int flag,
|
||||
}
|
||||
|
||||
while (1) {
|
||||
- usb_gadget_handle_interrupts(controller_index);
|
||||
+ dm_usb_gadget_handle_interrupts(udc);
|
||||
|
||||
rc = fsg_main_thread(NULL);
|
||||
if (rc) {
|
||||
@@ -237,7 +235,7 @@ static int do_usb_mass_storage(struct cmd_tbl *cmdtp, int flag,
|
||||
cleanup_register:
|
||||
g_dnl_unregister();
|
||||
cleanup_board:
|
||||
- usb_gadget_release(controller_index);
|
||||
+ udc_device_put(udc);
|
||||
cleanup_ums_init:
|
||||
ums_fini();
|
||||
|
||||
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/usb/gadget/f_mass_storage.c
|
||||
+++ b/drivers/usb/gadget/f_mass_storage.c
|
||||
@@ -240,6 +240,7 @@
|
||||
/* #define DUMP_MSGS */
|
||||
|
||||
#include <config.h>
|
||||
+#include <div64.h>
|
||||
#include <hexdump.h>
|
||||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
@@ -327,6 +328,7 @@ struct fsg_common {
|
||||
unsigned int short_packet_received:1;
|
||||
unsigned int bad_lun_okay:1;
|
||||
unsigned int running:1;
|
||||
+ unsigned int eject:1;
|
||||
|
||||
int thread_wakeup_needed;
|
||||
struct completion thread_notifier;
|
||||
@@ -435,7 +437,7 @@ static void set_bulk_out_req_length(struct fsg_common *common,
|
||||
static struct ums *ums;
|
||||
static int ums_count;
|
||||
static struct fsg_common *the_fsg_common;
|
||||
-static unsigned int controller_index;
|
||||
+static struct udevice *udcdev;
|
||||
|
||||
static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
|
||||
{
|
||||
@@ -669,6 +671,10 @@ static int sleep_thread(struct fsg_common *common)
|
||||
}
|
||||
|
||||
if (k == 10) {
|
||||
+ /* Handle START-STOP UNIT */
|
||||
+ if (common->eject)
|
||||
+ return -EPIPE;
|
||||
+
|
||||
/* Handle CTRL+C */
|
||||
if (ctrlc())
|
||||
return -EPIPE;
|
||||
@@ -680,7 +686,7 @@ static int sleep_thread(struct fsg_common *common)
|
||||
k = 0;
|
||||
}
|
||||
|
||||
- usb_gadget_handle_interrupts(controller_index);
|
||||
+ dm_usb_gadget_handle_interrupts(udcdev);
|
||||
}
|
||||
common->thread_wakeup_needed = 0;
|
||||
return rc;
|
||||
@@ -719,12 +725,13 @@ static int do_read(struct fsg_common *common)
|
||||
curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
return -EINVAL;
|
||||
}
|
||||
- file_offset = ((loff_t) lba) << 9;
|
||||
+ file_offset = ((loff_t)lba) << curlun->blkbits;
|
||||
|
||||
/* Carry out the file reads */
|
||||
amount_left = common->data_size_from_cmnd;
|
||||
- if (unlikely(amount_left == 0))
|
||||
+ if (unlikely(amount_left == 0)) {
|
||||
return -EIO; /* No default reply */
|
||||
+ }
|
||||
|
||||
for (;;) {
|
||||
|
||||
@@ -763,13 +770,13 @@ static int do_read(struct fsg_common *common)
|
||||
|
||||
/* Perform the read */
|
||||
rc = ums[common->lun].read_sector(&ums[common->lun],
|
||||
- file_offset / SECTOR_SIZE,
|
||||
- amount / SECTOR_SIZE,
|
||||
+ lldiv(file_offset, curlun->blksize),
|
||||
+ lldiv(amount, curlun->blksize),
|
||||
(char __user *)bh->buf);
|
||||
if (!rc)
|
||||
return -EIO;
|
||||
|
||||
- nread = rc * SECTOR_SIZE;
|
||||
+ nread = rc * curlun->blksize;
|
||||
|
||||
VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
|
||||
(unsigned long long) file_offset,
|
||||
@@ -782,7 +789,7 @@ static int do_read(struct fsg_common *common)
|
||||
} else if (nread < amount) {
|
||||
LDBG(curlun, "partial file read: %d/%u\n",
|
||||
(int) nread, amount);
|
||||
- nread -= (nread & 511); /* Round down to a block */
|
||||
+ nread -= (nread & (curlun->blksize - 1)); /* Round down to a block */
|
||||
}
|
||||
file_offset += nread;
|
||||
amount_left -= nread;
|
||||
@@ -856,7 +863,7 @@ static int do_write(struct fsg_common *common)
|
||||
|
||||
/* Carry out the file writes */
|
||||
get_some_more = 1;
|
||||
- file_offset = usb_offset = ((loff_t) lba) << 9;
|
||||
+ file_offset = usb_offset = ((loff_t)lba) << curlun->blkbits;
|
||||
amount_left_to_req = common->data_size_from_cmnd;
|
||||
amount_left_to_write = common->data_size_from_cmnd;
|
||||
|
||||
@@ -888,7 +895,7 @@ static int do_write(struct fsg_common *common)
|
||||
curlun->info_valid = 1;
|
||||
continue;
|
||||
}
|
||||
- amount -= (amount & 511);
|
||||
+ amount -= (amount & (curlun->blksize - 1));
|
||||
if (amount == 0) {
|
||||
|
||||
/* Why were we were asked to transfer a
|
||||
@@ -937,12 +944,12 @@ static int do_write(struct fsg_common *common)
|
||||
|
||||
/* Perform the write */
|
||||
rc = ums[common->lun].write_sector(&ums[common->lun],
|
||||
- file_offset / SECTOR_SIZE,
|
||||
- amount / SECTOR_SIZE,
|
||||
+ lldiv(file_offset, curlun->blksize),
|
||||
+ lldiv(amount, curlun->blksize),
|
||||
(char __user *)bh->buf);
|
||||
if (!rc)
|
||||
return -EIO;
|
||||
- nwritten = rc * SECTOR_SIZE;
|
||||
+ nwritten = rc * curlun->blksize;
|
||||
|
||||
VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
|
||||
(unsigned long long) file_offset,
|
||||
@@ -955,7 +962,7 @@ static int do_write(struct fsg_common *common)
|
||||
} else if (nwritten < amount) {
|
||||
LDBG(curlun, "partial file write: %d/%u\n",
|
||||
(int) nwritten, amount);
|
||||
- nwritten -= (nwritten & 511);
|
||||
+ nwritten -= (nwritten & (curlun->blksize - 1));
|
||||
/* Round down to a block */
|
||||
}
|
||||
file_offset += nwritten;
|
||||
@@ -1029,8 +1036,8 @@ static int do_verify(struct fsg_common *common)
|
||||
return -EIO; /* No default reply */
|
||||
|
||||
/* Prepare to carry out the file verify */
|
||||
- amount_left = verification_length << 9;
|
||||
- file_offset = ((loff_t) lba) << 9;
|
||||
+ amount_left = verification_length << curlun->blkbits;
|
||||
+ file_offset = ((loff_t) lba) << curlun->blkbits;
|
||||
|
||||
/* Write out all the dirty buffers before invalidating them */
|
||||
|
||||
@@ -1053,12 +1060,12 @@ static int do_verify(struct fsg_common *common)
|
||||
|
||||
/* Perform the read */
|
||||
rc = ums[common->lun].read_sector(&ums[common->lun],
|
||||
- file_offset / SECTOR_SIZE,
|
||||
- amount / SECTOR_SIZE,
|
||||
+ lldiv(file_offset, curlun->blksize),
|
||||
+ lldiv(amount, curlun->blksize),
|
||||
(char __user *)bh->buf);
|
||||
if (!rc)
|
||||
return -EIO;
|
||||
- nread = rc * SECTOR_SIZE;
|
||||
+ nread = rc * curlun->blksize;
|
||||
|
||||
VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
|
||||
(unsigned long long) file_offset,
|
||||
@@ -1070,7 +1077,7 @@ static int do_verify(struct fsg_common *common)
|
||||
} else if (nread < amount) {
|
||||
LDBG(curlun, "partial file verify: %d/%u\n",
|
||||
(int) nread, amount);
|
||||
- nread -= (nread & 511); /* Round down to a sector */
|
||||
+ nread -= (nread & (curlun->blksize - 1)); /* Round down to a sector */
|
||||
}
|
||||
if (nread == 0) {
|
||||
curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
|
||||
@@ -1117,7 +1124,7 @@ static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh)
|
||||
{
|
||||
struct fsg_lun *curlun = &common->luns[common->lun];
|
||||
u8 *buf = (u8 *) bh->buf;
|
||||
- u32 sd, sdinfo;
|
||||
+ u32 sd, sdinfo = 0;
|
||||
int valid;
|
||||
|
||||
/*
|
||||
@@ -1145,7 +1152,6 @@ static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh)
|
||||
if (!curlun) { /* Unsupported LUNs are okay */
|
||||
common->bad_lun_okay = 1;
|
||||
sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
|
||||
- sdinfo = 0;
|
||||
valid = 0;
|
||||
} else {
|
||||
sd = curlun->sense_data;
|
||||
@@ -1179,7 +1185,7 @@ static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh)
|
||||
|
||||
put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
|
||||
/* Max logical block */
|
||||
- put_unaligned_be32(512, &buf[4]); /* Block length */
|
||||
+ put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */
|
||||
return 8;
|
||||
}
|
||||
|
||||
@@ -1326,6 +1332,8 @@ static int do_start_stop(struct fsg_common *common)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ common->eject = 1;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1364,7 +1372,7 @@ static int do_read_format_capacities(struct fsg_common *common,
|
||||
|
||||
put_unaligned_be32(curlun->num_sectors, &buf[0]);
|
||||
/* Number of blocks */
|
||||
- put_unaligned_be32(512, &buf[4]); /* Block length */
|
||||
+ put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */
|
||||
buf[4] = 0x02; /* Current capacity */
|
||||
return 12;
|
||||
}
|
||||
@@ -1775,6 +1783,16 @@ static int check_command(struct fsg_common *common, int cmnd_size,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* wrapper of check_command for data size in blocks handling */
|
||||
+static int check_command_size_in_blocks(struct fsg_common *common,
|
||||
+ int cmnd_size, enum data_direction data_dir,
|
||||
+ unsigned int mask, int needs_medium, const char *name)
|
||||
+{
|
||||
+ common->data_size_from_cmnd <<= common->luns[common->lun].blkbits;
|
||||
+ return check_command(common, cmnd_size, data_dir,
|
||||
+ mask, needs_medium, name);
|
||||
+}
|
||||
+
|
||||
|
||||
static int do_scsi_command(struct fsg_common *common)
|
||||
{
|
||||
@@ -1859,30 +1877,30 @@ static int do_scsi_command(struct fsg_common *common)
|
||||
|
||||
case SC_READ_6:
|
||||
i = common->cmnd[4];
|
||||
- common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
|
||||
- reply = check_command(common, 6, DATA_DIR_TO_HOST,
|
||||
- (7<<1) | (1<<4), 1,
|
||||
- "READ(6)");
|
||||
+ common->data_size_from_cmnd = (i == 0 ? 256 : i);
|
||||
+ reply = check_command_size_in_blocks(common, 6, DATA_DIR_TO_HOST,
|
||||
+ (7<<1) | (1<<4), 1,
|
||||
+ "READ(6)");
|
||||
if (reply == 0)
|
||||
reply = do_read(common);
|
||||
break;
|
||||
|
||||
case SC_READ_10:
|
||||
common->data_size_from_cmnd =
|
||||
- get_unaligned_be16(&common->cmnd[7]) << 9;
|
||||
- reply = check_command(common, 10, DATA_DIR_TO_HOST,
|
||||
- (1<<1) | (0xf<<2) | (3<<7), 1,
|
||||
- "READ(10)");
|
||||
+ get_unaligned_be16(&common->cmnd[7]);
|
||||
+ reply = check_command_size_in_blocks(common, 10, DATA_DIR_TO_HOST,
|
||||
+ (1<<1) | (0xf<<2) | (3<<7), 1,
|
||||
+ "READ(10)");
|
||||
if (reply == 0)
|
||||
reply = do_read(common);
|
||||
break;
|
||||
|
||||
case SC_READ_12:
|
||||
common->data_size_from_cmnd =
|
||||
- get_unaligned_be32(&common->cmnd[6]) << 9;
|
||||
- reply = check_command(common, 12, DATA_DIR_TO_HOST,
|
||||
- (1<<1) | (0xf<<2) | (0xf<<6), 1,
|
||||
- "READ(12)");
|
||||
+ get_unaligned_be32(&common->cmnd[6]);
|
||||
+ reply = check_command_size_in_blocks(common, 12, DATA_DIR_TO_HOST,
|
||||
+ (1<<1) | (0xf<<2) | (0xf<<6), 1,
|
||||
+ "READ(12)");
|
||||
if (reply == 0)
|
||||
reply = do_read(common);
|
||||
break;
|
||||
@@ -1977,30 +1995,30 @@ static int do_scsi_command(struct fsg_common *common)
|
||||
|
||||
case SC_WRITE_6:
|
||||
i = common->cmnd[4];
|
||||
- common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
|
||||
- reply = check_command(common, 6, DATA_DIR_FROM_HOST,
|
||||
- (7<<1) | (1<<4), 1,
|
||||
- "WRITE(6)");
|
||||
+ common->data_size_from_cmnd = (i == 0 ? 256 : i);
|
||||
+ reply = check_command_size_in_blocks(common, 6, DATA_DIR_FROM_HOST,
|
||||
+ (7<<1) | (1<<4), 1,
|
||||
+ "WRITE(6)");
|
||||
if (reply == 0)
|
||||
reply = do_write(common);
|
||||
break;
|
||||
|
||||
case SC_WRITE_10:
|
||||
common->data_size_from_cmnd =
|
||||
- get_unaligned_be16(&common->cmnd[7]) << 9;
|
||||
- reply = check_command(common, 10, DATA_DIR_FROM_HOST,
|
||||
- (1<<1) | (0xf<<2) | (3<<7), 1,
|
||||
- "WRITE(10)");
|
||||
+ get_unaligned_be16(&common->cmnd[7]);
|
||||
+ reply = check_command_size_in_blocks(common, 10, DATA_DIR_FROM_HOST,
|
||||
+ (1<<1) | (0xf<<2) | (3<<7), 1,
|
||||
+ "WRITE(10)");
|
||||
if (reply == 0)
|
||||
reply = do_write(common);
|
||||
break;
|
||||
|
||||
case SC_WRITE_12:
|
||||
common->data_size_from_cmnd =
|
||||
- get_unaligned_be32(&common->cmnd[6]) << 9;
|
||||
- reply = check_command(common, 12, DATA_DIR_FROM_HOST,
|
||||
- (1<<1) | (0xf<<2) | (0xf<<6), 1,
|
||||
- "WRITE(12)");
|
||||
+ get_unaligned_be32(&common->cmnd[6]);
|
||||
+ reply = check_command_size_in_blocks(common, 12, DATA_DIR_FROM_HOST,
|
||||
+ (1<<1) | (0xf<<2) | (0xf<<6), 1,
|
||||
+ "WRITE(12)");
|
||||
if (reply == 0)
|
||||
reply = do_write(common);
|
||||
break;
|
||||
@@ -2491,7 +2509,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
|
||||
for (i = 0; i < nluns; i++) {
|
||||
common->luns[i].removable = 1;
|
||||
|
||||
- rc = fsg_lun_open(&common->luns[i], ums[i].num_sectors, "");
|
||||
+ rc = fsg_lun_open(&common->luns[i], ums[i].num_sectors, ums->block_dev.blksz, "");
|
||||
if (rc)
|
||||
goto error_luns;
|
||||
}
|
||||
@@ -2765,11 +2783,11 @@ int fsg_add(struct usb_configuration *c)
|
||||
return fsg_bind_config(c->cdev, c, fsg_common);
|
||||
}
|
||||
|
||||
-int fsg_init(struct ums *ums_devs, int count, unsigned int controller_idx)
|
||||
+int fsg_init(struct ums *ums_devs, int count, struct udevice *udc)
|
||||
{
|
||||
ums = ums_devs;
|
||||
ums_count = count;
|
||||
- controller_index = controller_idx;
|
||||
+ udcdev = udc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/usb/gadget/storage_common.c
|
||||
+++ b/drivers/usb/gadget/storage_common.c
|
||||
@@ -269,6 +269,7 @@ struct device_attribute { int i; };
|
||||
#define ETOOSMALL 525
|
||||
|
||||
#include <log.h>
|
||||
+#include <linux/log2.h>
|
||||
#include <usb_mass_storage.h>
|
||||
#include <dm/device_compat.h>
|
||||
|
||||
@@ -290,6 +291,8 @@ struct fsg_lun {
|
||||
u32 sense_data;
|
||||
u32 sense_data_info;
|
||||
u32 unit_attention_data;
|
||||
+ unsigned int blkbits;
|
||||
+ unsigned int blksize; /* logical block size of bound block device */
|
||||
|
||||
struct device dev;
|
||||
};
|
||||
@@ -566,7 +569,7 @@ static struct usb_gadget_strings fsg_stringtab = {
|
||||
*/
|
||||
|
||||
static int fsg_lun_open(struct fsg_lun *curlun, unsigned int num_sectors,
|
||||
- const char *filename)
|
||||
+ unsigned int sector_size, const char *filename)
|
||||
{
|
||||
int ro;
|
||||
|
||||
@@ -574,9 +577,12 @@ static int fsg_lun_open(struct fsg_lun *curlun, unsigned int num_sectors,
|
||||
ro = curlun->initially_ro;
|
||||
|
||||
curlun->ro = ro;
|
||||
- curlun->file_length = num_sectors << 9;
|
||||
+ curlun->file_length = num_sectors * sector_size;
|
||||
curlun->num_sectors = num_sectors;
|
||||
- debug("open backing file: %s\n", filename);
|
||||
+ curlun->blksize = sector_size;
|
||||
+ curlun->blkbits = order_base_2(sector_size >> 9) + 9;
|
||||
+ debug("blksize: %u\n", sector_size);
|
||||
+ debug("open backing file: '%s'\n", filename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/include/usb_mass_storage.h b/include/usb_mass_storage.h
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/include/usb_mass_storage.h
|
||||
+++ b/include/usb_mass_storage.h
|
||||
@@ -7,7 +7,6 @@
|
||||
#ifndef __USB_MASS_STORAGE_H__
|
||||
#define __USB_MASS_STORAGE_H__
|
||||
|
||||
-#define SECTOR_SIZE 0x200
|
||||
#include <part.h>
|
||||
#include <linux/usb/composite.h>
|
||||
|
||||
@@ -25,7 +24,7 @@ struct ums {
|
||||
struct blk_desc block_dev;
|
||||
};
|
||||
|
||||
-int fsg_init(struct ums *ums_devs, int count, unsigned int controller_idx);
|
||||
+int fsg_init(struct ums *ums_devs, int count, struct udevice *udc);
|
||||
void fsg_cleanup(void);
|
||||
int fsg_main_thread(void *);
|
||||
int fsg_add(struct usb_configuration *c);
|
||||
--
|
||||
Armbian
|
||||
|
||||
@ -0,0 +1,518 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Qu Wenruo <wqu@suse.com>
|
||||
Date: Fri, 30 Dec 2022 09:07:05 +0800
|
||||
Subject: UPSTREAM: multiple fixes for btrfs
|
||||
|
||||
fs: btrfs: Do not free multi when guaranteed to be NULL
|
||||
|
||||
multi is guaranteed to be NULL in the first two error exit paths so the
|
||||
attempt to free it is not needed. Remove those calls.
|
||||
|
||||
This issue found by Smatch.
|
||||
|
||||
Signed-off-by: Andrew Goodbody <andrew.goodbody@linaro.org>
|
||||
(cherry picked from commit 9204cae0937c0e26fcff1ee08e51ef37f59844fe)
|
||||
|
||||
fs: btrfs: hide duplicate 'Cannot lookup file' error on 'load'
|
||||
|
||||
Running commands such as 'load mmc 2:1 $addr $path' when path does not
|
||||
exists will print an error twice if the file does not exist, e.g.:
|
||||
```
|
||||
Cannot lookup file boot/boot.scr
|
||||
Failed to load 'boot/boot.scr'
|
||||
```
|
||||
(where the first line is printed by btrfs and the second by common fs
|
||||
code)
|
||||
|
||||
Historically other filesystems such as ext4 or fat have not been
|
||||
printing a message here, so do the same here to avoid duplicate.
|
||||
|
||||
The other error messages in this function are also somewhat redundant,
|
||||
but bring useful diagnostics if they happen somewhere, so have been left
|
||||
as printf.
|
||||
|
||||
Note that if a user wants no message to be printed for optional file
|
||||
loads, they have to check for file existence first with other commands
|
||||
such as 'size'.
|
||||
|
||||
Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
|
||||
Reviewed-by: Qu Wenruo <wqu@suse.com>
|
||||
(cherry picked from commit 6e988fde65b0a89d49c20553d47a8ec1e5461c12)
|
||||
|
||||
fs: btrfs: fix out of bounds write
|
||||
|
||||
Fix btrfs_read/read_and_truncate_page write out of bounds of destination
|
||||
buffer. Old behavior break bootstd malloc'd buffers of exact file size.
|
||||
Previously this OOB write have not been noticed because distroboot usually
|
||||
read files into huge static memory areas.
|
||||
|
||||
Signed-off-by: Alex Shumsky <alexthreed@gmail.com>
|
||||
Fixes: e342718 ("fs: btrfs: Implement btrfs_file_read()")
|
||||
Reviewed-by: Qu Wenruo <wqu@suse.com>
|
||||
(cherry picked from commit ee1941e4fec601a8444f49c7dad04ad700d501a6)
|
||||
|
||||
fs: btrfs: fix reading when length specified
|
||||
|
||||
The btrfs read function limits the read length to ensure that it
|
||||
and the read offset do not together exceed the size of the file.
|
||||
However, this size was only being queried if the read length was
|
||||
passed a value of zero (meaning "whole file"), and the size is
|
||||
defaulted to 0 otherwise. This means the clamp will just zero out
|
||||
the length if one is specified, preventing reading of the file.
|
||||
|
||||
Fix this by checking the file size unconditionally, and unifying
|
||||
the default length and clamping logic as a single range check instead.
|
||||
|
||||
This bug was discovered when trying to boot Linux with initrd= via
|
||||
'bootefi' from a btrfs partition. The EFI stub entered an infinite
|
||||
loop of zero-length reads while trying to read the initrd, and the
|
||||
boot process stalled indefinitely.
|
||||
|
||||
Signed-off-by: Sam Edwards <CFSworks@gmail.com>
|
||||
Reviewed-by: Qu Wenruo <wqu@suse.com>
|
||||
(cherry picked from commit 6d6ea52b629c384fb8605678b9003d2a077f9148)
|
||||
|
||||
btrfs: fix some error checking for btrfs_decompress()
|
||||
|
||||
The btrfs_decompress() function mostly (u32)-1 on error but it can
|
||||
also return -EPERM or other kernel error codes from zstd_decompress().
|
||||
The "ret" variable is an int, so we could just check for negatives.
|
||||
|
||||
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
|
||||
Reviewed-by: Qu Wenruo <wqu@suse.com>
|
||||
(cherry picked from commit 08404fa2087946bb370430d466fe5011f18ef072)
|
||||
|
||||
fs: btrfs: Prevent error pointer dereference in list_subvolums()
|
||||
|
||||
If btrfs_read_fs_root() fails with -ENOENT, then we go to the next
|
||||
entry. Fine. But if it fails for a different reason then we need
|
||||
to clean up and return an error code. In the current code it
|
||||
doesn't clean up but instead dereferences "root" and crashes.
|
||||
|
||||
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
|
||||
Reviewed-by: Marek Behun <kabel@kernel.org>
|
||||
Reviewed-by: Qu Wenruo <wqu@suse.com>
|
||||
(cherry picked from commit c331efd08766aa610aa14c957856ef5b0fa915df)
|
||||
|
||||
fs/btrfs: use asm/unaligned.h
|
||||
|
||||
Use asm/unaligned.h instead of linux/unaligned/access_ok.h for unaligned
|
||||
access. This is needed on architectures that doesn't handle unaligned
|
||||
accesses directly.
|
||||
|
||||
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
|
||||
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
|
||||
(cherry picked from commit 6ba08b3f56c93d2e97e5be3e9deccadd1e8c0796)
|
||||
|
||||
btrfs: fix offset when reading compressed extents
|
||||
|
||||
btrfs_read_extent_reg correctly computed the extent offset in the
|
||||
BTRFS_COMPRESS_NONE case, but did not account for the 'offset - key.offset'
|
||||
part correctly in the compressed case, making the function read
|
||||
incorrect data.
|
||||
|
||||
In the case I examined, the last 4k of a file was corrupted and
|
||||
contained data from a few blocks prior, e.g. reading a 10k file with a
|
||||
single extent:
|
||||
btrfs_file_read()
|
||||
-> btrfs_read_extent_reg
|
||||
(aligned part loop, until 8k)
|
||||
-> read_and_truncate_page
|
||||
-> btrfs_read_extent_reg
|
||||
(re-reads the last extent from 8k to the end,
|
||||
incorrectly reading the first 2k of data)
|
||||
|
||||
This can be reproduced as follow:
|
||||
$ truncate -s 200M btr
|
||||
$ mount btr -o compress /mnt
|
||||
$ pat() { dd if=/dev/zero bs=1M count=$1 iflag=count_bytes status=none | tr '\0' "\\$2"; }
|
||||
$ { pat 4K 1; pat 4K 2; pat 2K 3; } > /mnt/file
|
||||
$ sync
|
||||
$ filefrag -v /mnt/file
|
||||
File size of /mnt/file is 10240 (3 blocks of 4096 bytes)
|
||||
ext: logical_offset: physical_offset: length: expected: flags:
|
||||
0: 0.. 2: 3328.. 3330: 3: last,encoded,eof
|
||||
$ umount /mnt
|
||||
|
||||
Then in u-boot:
|
||||
=> load scsi 0 2000000 file
|
||||
10240 bytes read in 3 ms (3.3 MiB/s)
|
||||
=> md 2001ff0
|
||||
02001ff0: 02020202 02020202 02020202 02020202 ................
|
||||
02002000: 01010101 01010101 01010101 01010101 ................
|
||||
02002010: 01010101 01010101 01010101 01010101 ................
|
||||
|
||||
(02002000 onwards should contain '03' pattern but went back to 01,
|
||||
start of the extent)
|
||||
|
||||
After patch, data is read properly:
|
||||
=> md 2001ff0
|
||||
02001ff0: 02020202 02020202 02020202 02020202 ................
|
||||
02002000: 03030303 03030303 03030303 03030303 ................
|
||||
02002010: 03030303 03030303 03030303 03030303 ................
|
||||
|
||||
Note that the code previously (before commit e3427184f38a ("fs: btrfs:
|
||||
Implement btrfs_file_read()")) did not split that read in two, so
|
||||
this is a regression even if the previous code might not have been
|
||||
handling offsets correctly either (something that booted now fails to
|
||||
boot)
|
||||
|
||||
Fixes: a26a6bedafcf ("fs: btrfs: Introduce btrfs_read_extent_inline() and btrfs_read_extent_reg()")
|
||||
Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
|
||||
Reviewed-by: Qu Wenruo <wqu@suse.com>
|
||||
(cherry picked from commit b1d3013d024086c042dbae4ddd99db56bb55b5e7)
|
||||
|
||||
fs: btrfs: limit the mapped length to the original length
|
||||
|
||||
[BUG]
|
||||
There is a bug report that btrfs driver caused hang during file read:
|
||||
|
||||
This breaks btrfs on the HiFive Unmatched.
|
||||
|
||||
=> pci enum
|
||||
PCIE-0: Link up (Gen1-x8, Bus0)
|
||||
=> nvme scan
|
||||
=> load nvme 0:2 0x8c000000 /boot/dtb/sifive/hifive-unmatched-a00.dtb
|
||||
[hangs]
|
||||
|
||||
[CAUSE]
|
||||
The reporter provided some debug output:
|
||||
|
||||
read_extent_data: cur=615817216, orig_len=16384, cur_len=16384
|
||||
read_extent_data: btrfs_map_block: cur_len=479944704; ret=0
|
||||
read_extent_data: ret=0
|
||||
read_extent_data: cur=615833600, orig_len=4096, cur_len=4096
|
||||
read_extent_data: btrfs_map_block: cur_len=479928320; ret=0
|
||||
|
||||
Note the second and the last line, the @cur_len is 450+MiB, which is
|
||||
almost a chunk size.
|
||||
|
||||
And inside __btrfs_map_block(), we limits the returned value to stripe
|
||||
length, but that's depending on the chunk type:
|
||||
|
||||
if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
|
||||
BTRFS_BLOCK_GROUP_RAID1C3 | BTRFS_BLOCK_GROUP_RAID1C4 |
|
||||
BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6 |
|
||||
BTRFS_BLOCK_GROUP_RAID10 |
|
||||
BTRFS_BLOCK_GROUP_DUP)) {
|
||||
/* we limit the length of each bio to what fits in a stripe */
|
||||
*length = min_t(u64, ce->size - offset,
|
||||
map->stripe_len - stripe_offset);
|
||||
} else {
|
||||
*length = ce->size - offset;
|
||||
}
|
||||
|
||||
This means, if the chunk is SINGLE profile, then we don't limit the
|
||||
returned length at all, and even for other profiles, we can still return
|
||||
a length much larger than the requested one.
|
||||
|
||||
[FIX]
|
||||
Properly clamp the returned length, preventing it from returning a much
|
||||
larger range than expected.
|
||||
|
||||
Reported-by: Andreas Schwab <schwab@linux-m68k.org>
|
||||
Signed-off-by: Qu Wenruo <wqu@suse.com>
|
||||
(cherry picked from commit 511a1303c9cf9663c7d4312e3a0693319f41095b)
|
||||
|
||||
fs/btrfs: handle data extents, which crosss stripe boundaries, correctly
|
||||
|
||||
[BUG]
|
||||
Since btrfs supports single device RAID0 at mkfs time after btrfs-progs
|
||||
v5.14, if we create a single device raid0 btrfs, and created a file
|
||||
crossing stripe boundary:
|
||||
|
||||
# mkfs.btrfs -m dup -d raid0 test.img
|
||||
# mount test.img mnt
|
||||
# xfs_io -f -c "pwrite 0 128K" mnt/file
|
||||
# umount mnt
|
||||
|
||||
Since btrfs is using 64K as stripe length, above 128K data write is
|
||||
definitely going to cross at least one stripe boundary.
|
||||
|
||||
Then u-boot would fail to read above 128K file:
|
||||
|
||||
=> host bind 0 /home/adam/test.img
|
||||
=> ls host 0
|
||||
< > 131072 Fri Dec 30 00:18:25 2022 file
|
||||
=> load host 0 0 file
|
||||
BTRFS: An error occurred while reading file file
|
||||
Failed to load 'file'
|
||||
|
||||
[CAUSE]
|
||||
Unlike tree blocks read, data extent reads doesn't consider cases in which
|
||||
one data extent can cross stripe boundary.
|
||||
|
||||
In read_data_extent(), we just call btrfs_map_block() once and read the
|
||||
first mapped range.
|
||||
|
||||
And if the first mapped range is smaller than the desired range, it
|
||||
would return error.
|
||||
|
||||
But since even single device btrfs can utilize RAID0 profiles, the first
|
||||
mapped range can only be at most 64K for RAID0 profiles, and cause false
|
||||
error.
|
||||
|
||||
[FIX]
|
||||
Just like read_whole_eb(), we should call btrfs_map_block() in a loop
|
||||
until we read all data.
|
||||
|
||||
Since we're here, also add extra error messages for the following cases:
|
||||
|
||||
- btrfs_map_block() failure
|
||||
We already have the error message for it.
|
||||
|
||||
- Missing device
|
||||
This should not happen, as we only support single device for now.
|
||||
|
||||
- __btrfs_devread() failure
|
||||
|
||||
With this bug fixed, btrfs driver of u-boot can properly read the above
|
||||
128K file, and have the correct content:
|
||||
|
||||
=> host bind 0 /home/adam/test.img
|
||||
=> ls host 0
|
||||
< > 131072 Fri Dec 30 00:18:25 2022 file
|
||||
=> load host 0 0 file
|
||||
131072 bytes read in 0 ms
|
||||
=> md5sum 0 0x20000
|
||||
md5 for 00000000 ... 0001ffff ==> d48858312a922db7eb86377f638dbc9f
|
||||
^^^ Above md5sum also matches.
|
||||
|
||||
Reported-by: Sam Winchenbach <swichenbach@tethers.com>
|
||||
Signed-off-by: Qu Wenruo <wqu@suse.com>
|
||||
(cherry picked from commit 11d567012558fab7da9d1189948cb6005c081ccd)
|
||||
---
|
||||
fs/btrfs/btrfs.c | 17 ++--
|
||||
fs/btrfs/crypto/hash.c | 2 +-
|
||||
fs/btrfs/disk-io.c | 49 +++++-----
|
||||
fs/btrfs/inode.c | 16 ++-
|
||||
fs/btrfs/subvolume.c | 1 +
|
||||
fs/btrfs/volumes.c | 4 +-
|
||||
6 files changed, 49 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/fs/btrfs/btrfs.c
|
||||
+++ b/fs/btrfs/btrfs.c
|
||||
@@ -193,7 +193,7 @@ int btrfs_size(const char *file, loff_t *size)
|
||||
ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID,
|
||||
file, &root, &ino, &type, 40);
|
||||
if (ret < 0) {
|
||||
- printf("Cannot lookup file %s\n", file);
|
||||
+ debug("Cannot lookup file %s\n", file);
|
||||
return ret;
|
||||
}
|
||||
if (type != BTRFS_FT_REG_FILE) {
|
||||
@@ -228,7 +228,7 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = current_fs_info;
|
||||
struct btrfs_root *root;
|
||||
- loff_t real_size = 0;
|
||||
+ loff_t real_size;
|
||||
u64 ino;
|
||||
u8 type;
|
||||
int ret;
|
||||
@@ -246,16 +246,13 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if (!len) {
|
||||
- ret = btrfs_size(file, &real_size);
|
||||
- if (ret < 0) {
|
||||
- error("Failed to get inode size: %s", file);
|
||||
- return ret;
|
||||
- }
|
||||
- len = real_size;
|
||||
+ ret = btrfs_size(file, &real_size);
|
||||
+ if (ret < 0) {
|
||||
+ error("Failed to get inode size: %s", file);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
- if (len > real_size - offset)
|
||||
+ if (!len || len > real_size - offset)
|
||||
len = real_size - offset;
|
||||
|
||||
ret = btrfs_file_read(root, ino, offset, len, buf);
|
||||
diff --git a/fs/btrfs/crypto/hash.c b/fs/btrfs/crypto/hash.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/fs/btrfs/crypto/hash.c
|
||||
+++ b/fs/btrfs/crypto/hash.c
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
+#include <asm/unaligned.h>
|
||||
#include <linux/xxhash.h>
|
||||
-#include <linux/unaligned/access_ok.h>
|
||||
#include <linux/types.h>
|
||||
#include <u-boot/sha256.h>
|
||||
#include <u-boot/blake2.h>
|
||||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/fs/btrfs/disk-io.c
|
||||
+++ b/fs/btrfs/disk-io.c
|
||||
@@ -540,34 +540,39 @@ struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
|
||||
int read_extent_data(struct btrfs_fs_info *fs_info, char *data, u64 logical,
|
||||
u64 *len, int mirror)
|
||||
{
|
||||
- u64 offset = 0;
|
||||
+ u64 orig_len = *len;
|
||||
+ u64 cur = logical;
|
||||
struct btrfs_multi_bio *multi = NULL;
|
||||
struct btrfs_device *device;
|
||||
int ret = 0;
|
||||
- u64 max_len = *len;
|
||||
|
||||
- ret = btrfs_map_block(fs_info, READ, logical, len, &multi, mirror,
|
||||
- NULL);
|
||||
- if (ret) {
|
||||
- fprintf(stderr, "Couldn't map the block %llu\n",
|
||||
- logical + offset);
|
||||
- goto err;
|
||||
- }
|
||||
- device = multi->stripes[0].dev;
|
||||
-
|
||||
- if (*len > max_len)
|
||||
- *len = max_len;
|
||||
- if (!device->desc || !device->part) {
|
||||
- ret = -EIO;
|
||||
- goto err;
|
||||
- }
|
||||
+ while (cur < logical + orig_len) {
|
||||
+ u64 cur_len = logical + orig_len - cur;
|
||||
|
||||
- ret = __btrfs_devread(device->desc, device->part, data, *len,
|
||||
- multi->stripes[0].physical);
|
||||
- if (ret != *len)
|
||||
- ret = -EIO;
|
||||
- else
|
||||
+ ret = btrfs_map_block(fs_info, READ, cur, &cur_len, &multi,
|
||||
+ mirror, NULL);
|
||||
+ if (ret) {
|
||||
+ error("Couldn't map the block %llu", cur);
|
||||
+ goto err;
|
||||
+ }
|
||||
+ device = multi->stripes[0].dev;
|
||||
+ if (!device->desc || !device->part) {
|
||||
+ error("devid %llu is missing", device->devid);
|
||||
+ ret = -EIO;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ ret = __btrfs_devread(device->desc, device->part,
|
||||
+ data + (cur - logical), cur_len,
|
||||
+ multi->stripes[0].physical);
|
||||
+ if (ret != cur_len) {
|
||||
+ error("read failed on devid %llu physical %llu",
|
||||
+ device->devid, multi->stripes[0].physical);
|
||||
+ ret = -EIO;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ cur += cur_len;
|
||||
ret = 0;
|
||||
+ }
|
||||
err:
|
||||
kfree(multi);
|
||||
return ret;
|
||||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/fs/btrfs/inode.c
|
||||
+++ b/fs/btrfs/inode.c
|
||||
@@ -390,7 +390,7 @@ int btrfs_read_extent_inline(struct btrfs_path *path,
|
||||
csize);
|
||||
ret = btrfs_decompress(btrfs_file_extent_compression(leaf, fi),
|
||||
cbuf, csize, dbuf, dsize);
|
||||
- if (ret == (u32)-1) {
|
||||
+ if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
@@ -500,7 +500,7 @@ int btrfs_read_extent_reg(struct btrfs_path *path,
|
||||
|
||||
ret = btrfs_decompress(btrfs_file_extent_compression(leaf, fi), cbuf,
|
||||
csize, dbuf, dsize);
|
||||
- if (ret == (u32)-1) {
|
||||
+ if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
@@ -511,7 +511,9 @@ int btrfs_read_extent_reg(struct btrfs_path *path,
|
||||
if (ret < dsize)
|
||||
memset(dbuf + ret, 0, dsize - ret);
|
||||
/* Then copy the needed part */
|
||||
- memcpy(dest, dbuf + btrfs_file_extent_offset(leaf, fi), len);
|
||||
+ memcpy(dest,
|
||||
+ dbuf + btrfs_file_extent_offset(leaf, fi) + offset - key.offset,
|
||||
+ len);
|
||||
ret = len;
|
||||
out:
|
||||
free(cbuf);
|
||||
@@ -638,7 +640,11 @@ static int read_and_truncate_page(struct btrfs_path *path,
|
||||
extent_type = btrfs_file_extent_type(leaf, fi);
|
||||
if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
|
||||
ret = btrfs_read_extent_inline(path, fi, buf);
|
||||
- memcpy(dest, buf + page_off, min(page_len, ret));
|
||||
+ if (ret < 0) {
|
||||
+ free(buf);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ memcpy(dest, buf + page_off, min3(page_len, ret, len));
|
||||
free(buf);
|
||||
return len;
|
||||
}
|
||||
@@ -650,7 +656,7 @@ static int read_and_truncate_page(struct btrfs_path *path,
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
- memcpy(dest, buf + page_off, page_len);
|
||||
+ memcpy(dest, buf + page_off, min(page_len, len));
|
||||
free(buf);
|
||||
return len;
|
||||
}
|
||||
diff --git a/fs/btrfs/subvolume.c b/fs/btrfs/subvolume.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/fs/btrfs/subvolume.c
|
||||
+++ b/fs/btrfs/subvolume.c
|
||||
@@ -199,6 +199,7 @@ static int list_subvolums(struct btrfs_fs_info *fs_info)
|
||||
ret = PTR_ERR(root);
|
||||
if (ret == -ENOENT)
|
||||
goto next;
|
||||
+ goto out;
|
||||
}
|
||||
ret = list_one_subvol(root, result);
|
||||
if (ret < 0)
|
||||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/fs/btrfs/volumes.c
|
||||
+++ b/fs/btrfs/volumes.c
|
||||
@@ -956,6 +956,7 @@ int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
|
||||
struct cache_extent *ce;
|
||||
struct map_lookup *map;
|
||||
+ u64 orig_len = *length;
|
||||
u64 offset;
|
||||
u64 stripe_offset;
|
||||
u64 *raid_map = NULL;
|
||||
@@ -972,12 +973,10 @@ int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
|
||||
again:
|
||||
ce = search_cache_extent(&map_tree->cache_tree, logical);
|
||||
if (!ce) {
|
||||
- kfree(multi);
|
||||
*length = (u64)-1;
|
||||
return -ENOENT;
|
||||
}
|
||||
if (ce->start > logical) {
|
||||
- kfree(multi);
|
||||
*length = ce->start - logical;
|
||||
return -ENOENT;
|
||||
}
|
||||
@@ -1047,6 +1046,7 @@ again:
|
||||
} else {
|
||||
*length = ce->size - offset;
|
||||
}
|
||||
+ *length = min_t(u64, *length, orig_len);
|
||||
|
||||
if (!multi_ret)
|
||||
goto out;
|
||||
--
|
||||
Armbian
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ricardo Pardini <ricardo@pardini.net>
|
||||
Date: Sun, 4 Jan 2026 15:58:51 +0100
|
||||
Subject: GENIO: radxa-nio-12l: Enable BTRFS and BZIP2 support
|
||||
|
||||
After cherry-picking from upstream, BTRFS should work, so enable it
|
||||
for the NIO-12L. Also add support for general BZIP2 compression.
|
||||
|
||||
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
|
||||
---
|
||||
configs/genio_1200_radxa_nio_12l_d16_defconfig | 2 ++
|
||||
configs/genio_1200_radxa_nio_12l_d4_defconfig | 2 ++
|
||||
configs/genio_1200_radxa_nio_12l_d8_defconfig | 2 ++
|
||||
3 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/configs/genio_1200_radxa_nio_12l_d16_defconfig b/configs/genio_1200_radxa_nio_12l_d16_defconfig
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/configs/genio_1200_radxa_nio_12l_d16_defconfig
|
||||
+++ b/configs/genio_1200_radxa_nio_12l_d16_defconfig
|
||||
@@ -53,6 +53,7 @@ CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
# CONFIG_CMD_ITEST is not set
|
||||
# CONFIG_CMD_BLOCK_CACHE is not set
|
||||
CONFIG_CMD_EFIDEBUG=y
|
||||
+CONFIG_CMD_BTRFS=y
|
||||
CONFIG_PARTITION_TYPE_GUID=y
|
||||
CONFIG_ENV_IS_IN_SCSI=y
|
||||
CONFIG_SYS_SCSI_ENV_DEV=1
|
||||
@@ -122,6 +123,7 @@ CONFIG_USB_ETHER=y
|
||||
CONFIG_UFS=y
|
||||
CONFIG_UFS_MEDIATEK=y
|
||||
CONFIG_WDT=y
|
||||
+CONFIG_BZIP2=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
CONFIG_EFI_SET_TIME=y
|
||||
CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
|
||||
diff --git a/configs/genio_1200_radxa_nio_12l_d4_defconfig b/configs/genio_1200_radxa_nio_12l_d4_defconfig
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/configs/genio_1200_radxa_nio_12l_d4_defconfig
|
||||
+++ b/configs/genio_1200_radxa_nio_12l_d4_defconfig
|
||||
@@ -53,6 +53,7 @@ CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
# CONFIG_CMD_ITEST is not set
|
||||
# CONFIG_CMD_BLOCK_CACHE is not set
|
||||
CONFIG_CMD_EFIDEBUG=y
|
||||
+CONFIG_CMD_BTRFS=y
|
||||
CONFIG_PARTITION_TYPE_GUID=y
|
||||
CONFIG_ENV_IS_IN_SCSI=y
|
||||
CONFIG_SYS_SCSI_ENV_DEV=1
|
||||
@@ -122,6 +123,7 @@ CONFIG_USB_ETHER=y
|
||||
CONFIG_UFS=y
|
||||
CONFIG_UFS_MEDIATEK=y
|
||||
CONFIG_WDT=y
|
||||
+CONFIG_BZIP2=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
CONFIG_EFI_SET_TIME=y
|
||||
CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
|
||||
diff --git a/configs/genio_1200_radxa_nio_12l_d8_defconfig b/configs/genio_1200_radxa_nio_12l_d8_defconfig
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/configs/genio_1200_radxa_nio_12l_d8_defconfig
|
||||
+++ b/configs/genio_1200_radxa_nio_12l_d8_defconfig
|
||||
@@ -53,6 +53,7 @@ CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
# CONFIG_CMD_ITEST is not set
|
||||
# CONFIG_CMD_BLOCK_CACHE is not set
|
||||
CONFIG_CMD_EFIDEBUG=y
|
||||
+CONFIG_CMD_BTRFS=y
|
||||
CONFIG_PARTITION_TYPE_GUID=y
|
||||
CONFIG_ENV_IS_IN_SCSI=y
|
||||
CONFIG_SYS_SCSI_ENV_DEV=1
|
||||
@@ -122,6 +123,7 @@ CONFIG_USB_ETHER=y
|
||||
CONFIG_UFS=y
|
||||
CONFIG_UFS_MEDIATEK=y
|
||||
CONFIG_WDT=y
|
||||
+CONFIG_BZIP2=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
CONFIG_EFI_SET_TIME=y
|
||||
CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
|
||||
--
|
||||
Armbian
|
||||
|
||||
Loading…
Reference in New Issue
Block a user