Merge branch '2023-08-22-assorted-code-cleanups' into next

- Assorted cleanups and fixes for a few tests, how we handle
  disks/partitions and bounce buffers.
This commit is contained in:
Tom Rini 2023-08-23 10:40:47 -04:00
commit 97841de680
11 changed files with 270 additions and 210 deletions

View file

@ -79,7 +79,7 @@ int bounce_buffer_stop(struct bounce_buffer *state)
{
if (state->flags & GEN_BB_WRITE) {
/* Invalidate cache so that CPU can see any newly DMA'd data */
dma_unmap_single((dma_addr_t)state->bounce_buffer,
dma_unmap_single((dma_addr_t)(uintptr_t)state->bounce_buffer,
state->len_aligned,
DMA_BIDIRECTIONAL);
}

View file

@ -17,227 +17,110 @@
#include <dm/device-internal.h>
#include <dm/lists.h>
int part_create_block_devices(struct udevice *blk_dev)
/**
* disk_blk_part_validate() - Check whether access to partition is within limits
*
* @dev: Device (partition udevice)
* @start: Start block for the access(from start of partition)
* @blkcnt: Number of blocks to access (within the partition)
* @return 0 on valid block range, or -ve on error.
*/
static int disk_blk_part_validate(struct udevice *dev, lbaint_t start, lbaint_t blkcnt)
{
int part, count;
struct blk_desc *desc = dev_get_uclass_plat(blk_dev);
struct disk_partition info;
struct disk_part *part_data;
char devname[32];
struct udevice *dev;
int ret;
struct disk_part *part = dev_get_uclass_plat(dev);
if (!CONFIG_IS_ENABLED(PARTITIONS) || !blk_enabled())
return 0;
if (device_get_uclass_id(dev) != UCLASS_PARTITION)
return -ENOSYS;
if (device_get_uclass_id(blk_dev) != UCLASS_BLK)
return 0;
if (start >= part->gpt_part_info.size)
return -E2BIG;
/* Add devices for each partition */
for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info))
continue;
snprintf(devname, sizeof(devname), "%s:%d", blk_dev->name,
part);
ret = device_bind_driver(blk_dev, "blk_partition",
strdup(devname), &dev);
if (ret)
return ret;
part_data = dev_get_uclass_plat(dev);
part_data->partnum = part;
part_data->gpt_part_info = info;
count++;
ret = device_probe(dev);
if (ret) {
debug("Can't probe\n");
count--;
device_unbind(dev);
continue;
}
}
debug("%s: %d partitions found in %s\n", __func__, count,
blk_dev->name);
if ((start + blkcnt) > part->gpt_part_info.size)
return -ERANGE;
return 0;
}
static ulong part_blk_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
/**
* disk_blk_part_offset() - Compute offset from start of block device
*
* @dev: Device (partition udevice)
* @start: Start block for the access (from start of partition)
* @return Start block for the access (from start of block device)
*/
static lbaint_t disk_blk_part_offset(struct udevice *dev, lbaint_t start)
{
struct udevice *parent;
struct disk_part *part;
const struct blk_ops *ops;
struct disk_part *part = dev_get_uclass_plat(dev);
parent = dev_get_parent(dev);
ops = blk_get_ops(parent);
if (!ops->read)
return -ENOSYS;
part = dev_get_uclass_plat(dev);
if (start >= part->gpt_part_info.size)
return 0;
if ((start + blkcnt) > part->gpt_part_info.size)
blkcnt = part->gpt_part_info.size - start;
start += part->gpt_part_info.start;
return ops->read(parent, start, blkcnt, buffer);
return start + part->gpt_part_info.start;
}
static ulong part_blk_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
{
struct udevice *parent;
struct disk_part *part;
const struct blk_ops *ops;
parent = dev_get_parent(dev);
ops = blk_get_ops(parent);
if (!ops->write)
return -ENOSYS;
part = dev_get_uclass_plat(dev);
if (start >= part->gpt_part_info.size)
return 0;
if ((start + blkcnt) > part->gpt_part_info.size)
blkcnt = part->gpt_part_info.size - start;
start += part->gpt_part_info.start;
return ops->write(parent, start, blkcnt, buffer);
}
static ulong part_blk_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
{
struct udevice *parent;
struct disk_part *part;
const struct blk_ops *ops;
parent = dev_get_parent(dev);
ops = blk_get_ops(parent);
if (!ops->erase)
return -ENOSYS;
part = dev_get_uclass_plat(dev);
if (start >= part->gpt_part_info.size)
return 0;
if ((start + blkcnt) > part->gpt_part_info.size)
blkcnt = part->gpt_part_info.size - start;
start += part->gpt_part_info.start;
return ops->erase(parent, start, blkcnt);
}
static const struct blk_ops blk_part_ops = {
.read = part_blk_read,
.write = part_blk_write,
.erase = part_blk_erase,
};
U_BOOT_DRIVER(blk_partition) = {
.name = "blk_partition",
.id = UCLASS_PARTITION,
.ops = &blk_part_ops,
};
/*
* BLOCK IO APIs
*/
static struct blk_desc *dev_get_blk(struct udevice *dev)
{
struct blk_desc *desc;
switch (device_get_uclass_id(dev)) {
/*
* We won't support UCLASS_BLK with dev_* interfaces.
*/
case UCLASS_PARTITION:
desc = dev_get_uclass_plat(dev_get_parent(dev));
break;
default:
desc = NULL;
break;
}
return desc;
}
/**
* disk_blk_read() - Read from a block device partition
*
* @dev: Device to read from (partition udevice)
* @start: Start block for the read (from start of partition)
* @blkcnt: Number of blocks to read (within the partition)
* @buffer: Place to put the data
* @return number of blocks read (which may be less than @blkcnt),
* or -ve on error. This never returns 0 unless @blkcnt is 0
*/
unsigned long disk_blk_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
{
struct blk_desc *desc;
const struct blk_ops *ops;
struct disk_part *part;
lbaint_t start_in_disk;
ulong blks_read;
int ret = disk_blk_part_validate(dev, start, blkcnt);
desc = dev_get_blk(dev);
if (!desc)
return -ENOSYS;
if (ret)
return ret;
ops = blk_get_ops(dev);
if (!ops->read)
return -ENOSYS;
start_in_disk = start;
if (device_get_uclass_id(dev) == UCLASS_PARTITION) {
part = dev_get_uclass_plat(dev);
start_in_disk += part->gpt_part_info.start;
}
if (blkcache_read(desc->uclass_id, desc->devnum, start_in_disk, blkcnt,
desc->blksz, buffer))
return blkcnt;
blks_read = ops->read(dev, start, blkcnt, buffer);
if (blks_read == blkcnt)
blkcache_fill(desc->uclass_id, desc->devnum, start_in_disk,
blkcnt, desc->blksz, buffer);
return blks_read;
return blk_read(dev_get_parent(dev), disk_blk_part_offset(dev, start),
blkcnt, buffer);
}
/**
* disk_blk_write() - Write to a block device
*
* @dev: Device to write to (partition udevice)
* @start: Start block for the write (from start of partition)
* @blkcnt: Number of blocks to write (within the partition)
* @buffer: Data to write
* @return number of blocks written (which may be less than @blkcnt),
* or -ve on error. This never returns 0 unless @blkcnt is 0
*/
unsigned long disk_blk_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
{
struct blk_desc *desc;
const struct blk_ops *ops;
int ret = disk_blk_part_validate(dev, start, blkcnt);
desc = dev_get_blk(dev);
if (!desc)
return -ENOSYS;
if (ret)
return ret;
ops = blk_get_ops(dev);
if (!ops->write)
return -ENOSYS;
blkcache_invalidate(desc->uclass_id, desc->devnum);
return ops->write(dev, start, blkcnt, buffer);
return blk_write(dev_get_parent(dev), disk_blk_part_offset(dev, start),
blkcnt, buffer);
}
/**
* disk_blk_erase() - Erase part of a block device
*
* @dev: Device to erase (partition udevice)
* @start: Start block for the erase (from start of partition)
* @blkcnt: Number of blocks to erase (within the partition)
* @return number of blocks erased (which may be less than @blkcnt),
* or -ve on error. This never returns 0 unless @blkcnt is 0
*/
unsigned long disk_blk_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
{
struct blk_desc *desc;
const struct blk_ops *ops;
int ret = disk_blk_part_validate(dev, start, blkcnt);
desc = dev_get_blk(dev);
if (!desc)
return -ENOSYS;
if (ret)
return ret;
ops = blk_get_ops(dev);
if (!ops->erase)
return -ENOSYS;
blkcache_invalidate(desc->uclass_id, desc->devnum);
return ops->erase(dev, start, blkcnt);
return blk_erase(dev_get_parent(dev), disk_blk_part_offset(dev, start),
blkcnt);
}
UCLASS_DRIVER(partition) = {
@ -245,3 +128,15 @@ UCLASS_DRIVER(partition) = {
.per_device_plat_auto = sizeof(struct disk_part),
.name = "partition",
};
static const struct blk_ops blk_part_ops = {
.read = disk_blk_read,
.write = disk_blk_write,
.erase = disk_blk_erase,
};
U_BOOT_DRIVER(blk_partition) = {
.name = "blk_partition",
.id = UCLASS_PARTITION,
.ops = &blk_part_ops,
};

View file

@ -207,8 +207,9 @@ static int part_get_info_extended(struct blk_desc *dev_desc,
struct disk_partition *info, uint disksig)
{
ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
struct disk_partition wdinfo = { 0 };
dos_partition_t *pt;
int i;
int i, ret;
int dos_type;
/* set a maximum recursion level */
@ -236,6 +237,10 @@ static int part_get_info_extended(struct blk_desc *dev_desc,
disksig = get_unaligned_le32(&buffer[DOS_PART_DISKSIG_OFFSET]);
#endif
ret = part_get_info_whole_disk(dev_desc, &wdinfo);
if (ret)
return ret;
/* Print all primary/logical partitions */
pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
for (i = 0; i < 4; i++, pt++) {
@ -247,7 +252,10 @@ static int part_get_info_extended(struct blk_desc *dev_desc,
(pt->sys_ind != 0) &&
(part_num == which_part) &&
(ext_part_sector == 0 || is_extended(pt->sys_ind) == 0)) {
info->blksz = DOS_PART_DEFAULT_SECTOR;
if (wdinfo.blksz > DOS_PART_DEFAULT_SECTOR)
info->blksz = wdinfo.blksz;
else
info->blksz = DOS_PART_DEFAULT_SECTOR;
info->start = (lbaint_t)(ext_part_sector +
get_unaligned_le32(pt->start4));
info->size = (lbaint_t)get_unaligned_le32(pt->size4);
@ -289,7 +297,10 @@ static int part_get_info_extended(struct blk_desc *dev_desc,
if (dos_type == DOS_PBR) {
info->start = 0;
info->size = dev_desc->lba;
info->blksz = DOS_PART_DEFAULT_SECTOR;
if (wdinfo.blksz > DOS_PART_DEFAULT_SECTOR)
info->blksz = wdinfo.blksz;
else
info->blksz = DOS_PART_DEFAULT_SECTOR;
info->bootable = 0;
strcpy((char *)info->type, "U-Boot");
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)

View file

@ -17,6 +17,8 @@
#include <dm/uclass-internal.h>
#include <linux/err.h>
#define blk_get_ops(dev) ((struct blk_ops *)(dev)->driver->ops)
static struct {
enum uclass_id id;
const char *name;
@ -444,6 +446,26 @@ int blk_get_device(int uclass_id, int devnum, struct udevice **devp)
return device_probe(*devp);
}
struct blk_bounce_buffer {
struct udevice *dev;
struct bounce_buffer state;
};
static int blk_buffer_aligned(struct bounce_buffer *state)
{
#if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
struct blk_bounce_buffer *bbstate =
container_of(state, struct blk_bounce_buffer, state);
struct udevice *dev = bbstate->dev;
const struct blk_ops *ops = blk_get_ops(dev);
if (ops->buffer_aligned)
return ops->buffer_aligned(dev, state);
#endif /* CONFIG_BOUNCE_BUFFER */
return 1; /* Default, any buffer is OK */
}
long blk_read(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buf)
{
struct blk_desc *desc = dev_get_uclass_plat(dev);
@ -456,7 +478,25 @@ long blk_read(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buf)
if (blkcache_read(desc->uclass_id, desc->devnum,
start, blkcnt, desc->blksz, buf))
return blkcnt;
blks_read = ops->read(dev, start, blkcnt, buf);
if (IS_ENABLED(CONFIG_BOUNCE_BUFFER)) {
struct blk_bounce_buffer bbstate = { .dev = dev };
int ret;
ret = bounce_buffer_start_extalign(&bbstate.state, buf,
blkcnt * desc->blksz,
GEN_BB_WRITE, desc->blksz,
blk_buffer_aligned);
if (ret)
return ret;
blks_read = ops->read(dev, start, blkcnt, bbstate.state.bounce_buffer);
bounce_buffer_stop(&bbstate.state);
} else {
blks_read = ops->read(dev, start, blkcnt, buf);
}
if (blks_read == blkcnt)
blkcache_fill(desc->uclass_id, desc->devnum, start, blkcnt,
desc->blksz, buf);
@ -469,13 +509,33 @@ long blk_write(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
{
struct blk_desc *desc = dev_get_uclass_plat(dev);
const struct blk_ops *ops = blk_get_ops(dev);
long blks_written;
if (!ops->write)
return -ENOSYS;
blkcache_invalidate(desc->uclass_id, desc->devnum);
return ops->write(dev, start, blkcnt, buf);
if (IS_ENABLED(CONFIG_BOUNCE_BUFFER)) {
struct blk_bounce_buffer bbstate = { .dev = dev };
int ret;
ret = bounce_buffer_start_extalign(&bbstate.state, (void *)buf,
blkcnt * desc->blksz,
GEN_BB_READ, desc->blksz,
blk_buffer_aligned);
if (ret)
return ret;
blks_written = ops->write(dev, start, blkcnt,
bbstate.state.bounce_buffer);
bounce_buffer_stop(&bbstate.state);
} else {
blks_written = ops->write(dev, start, blkcnt, buf);
}
return blks_written;
}
long blk_erase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt)
@ -766,6 +826,54 @@ int blk_unbind_all(int uclass_id)
return 0;
}
static int part_create_block_devices(struct udevice *blk_dev)
{
int part, count;
struct blk_desc *desc = dev_get_uclass_plat(blk_dev);
struct disk_partition info;
struct disk_part *part_data;
char devname[32];
struct udevice *dev;
int ret;
if (!CONFIG_IS_ENABLED(PARTITIONS) || !blk_enabled())
return 0;
if (device_get_uclass_id(blk_dev) != UCLASS_BLK)
return 0;
/* Add devices for each partition */
for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info))
continue;
snprintf(devname, sizeof(devname), "%s:%d", blk_dev->name,
part);
ret = device_bind_driver(blk_dev, "blk_partition",
strdup(devname), &dev);
if (ret)
return ret;
part_data = dev_get_uclass_plat(dev);
part_data->partnum = part;
part_data->gpt_part_info = info;
count++;
ret = device_probe(dev);
if (ret) {
debug("Can't probe\n");
count--;
device_unbind(dev);
continue;
}
}
debug("%s: %d partitions found in %s\n", __func__, count,
blk_dev->name);
return 0;
}
static int blk_post_probe(struct udevice *dev)
{
if (CONFIG_IS_ENABLED(PARTITIONS) && blk_enabled()) {

View file

@ -274,6 +274,18 @@ static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
__func__, start, smallblks, buf_addr);
return blkcnt;
}
#if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
static int scsi_buffer_aligned(struct udevice *dev, struct bounce_buffer *state)
{
struct scsi_ops *ops = scsi_get_ops(dev->parent);
if (ops->buffer_aligned)
return ops->buffer_aligned(dev->parent, state);
return 1;
}
#endif /* CONFIG_BOUNCE_BUFFER */
#endif
#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) && \
@ -720,6 +732,9 @@ int scsi_scan(bool verbose)
static const struct blk_ops scsi_blk_ops = {
.read = scsi_read,
.write = scsi_write,
#if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
.buffer_aligned = scsi_buffer_aligned,
#endif /* CONFIG_BOUNCE_BUFFER */
};
U_BOOT_DRIVER(scsi_blk) = {

View file

@ -7,6 +7,7 @@
#ifndef BLK_H
#define BLK_H
#include <bouncebuf.h>
#include <dm/uclass-id.h>
#include <efi.h>
@ -260,9 +261,25 @@ struct blk_ops {
* @return 0 if OK, -ve on error
*/
int (*select_hwpart)(struct udevice *dev, int hwpart);
};
#define blk_get_ops(dev) ((struct blk_ops *)(dev)->driver->ops)
#if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
/**
* buffer_aligned() - test memory alignment of block operation buffer
*
* Some devices have limited DMA capabilities and require that the
* buffers passed to them fit specific properties. This optional
* callback can be used to indicate whether a buffer alignment is
* suitable for the device DMA or not, and trigger use of generic
* bounce buffer implementation to help use of unsuitable buffers
* at the expense of performance degradation.
*
* @dev: Block device associated with the request
* @state: Bounce buffer state
* @return 1 if OK, 0 if unaligned
*/
int (*buffer_aligned)(struct udevice *dev, struct bounce_buffer *state);
#endif /* CONFIG_BOUNCE_BUFFER */
};
/*
* These functions should take struct udevice instead of struct blk_desc,

View file

@ -315,15 +315,6 @@ part_get_info_by_dev_and_name_or_num(const char *dev_iface,
int part_get_bootable(struct blk_desc *desc);
struct udevice;
/**
* part_create_block_devices - Create block devices for disk partitions
*
* Create UCLASS_PARTITION udevices for each of disk partitions in @parent
*
* @blk_dev: Whole disk device
*/
int part_create_block_devices(struct udevice *blk_dev);
/**
* disk_blk_read() - read blocks from a disk partition
*

View file

@ -7,6 +7,7 @@
#define _SCSI_H
#include <asm/cache.h>
#include <bouncebuf.h>
#include <linux/dma-direction.h>
/* Fix this to the maximum */
@ -298,6 +299,24 @@ struct scsi_ops {
* @return 0 if OK, -ve on error
*/
int (*bus_reset)(struct udevice *dev);
#if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
/**
* buffer_aligned() - test memory alignment of block operation buffer
*
* Some devices have limited DMA capabilities and require that the
* buffers passed to them fit specific properties. This optional
* callback can be used to indicate whether a buffer alignment is
* suitable for the device DMA or not, and trigger use of generic
* bounce buffer implementation to help use of unsuitable buffers
* at the expense of performance degradation.
*
* @dev: Block device associated with the request
* @state: Bounce buffer state
* @return 1 if OK, 0 if unaligned
*/
int (*buffer_aligned)(struct udevice *dev, struct bounce_buffer *state);
#endif /* CONFIG_BOUNCE_BUFFER */
};
#define scsi_get_ops(dev) ((struct scsi_ops *)(dev)->driver->ops)

View file

@ -716,7 +716,7 @@ restart:
case NETLOOP_SUCCESS:
net_cleanup_loop();
if (net_boot_file_size > 0) {
printf("Bytes transferred = %d (%x hex)\n",
printf("Bytes transferred = %u (%x hex)\n",
net_boot_file_size, net_boot_file_size);
env_set_hex("filesize", net_boot_file_size);
env_set_hex("fileaddr", image_load_addr);

View file

@ -201,7 +201,7 @@ static char ut_help_text[] =
"\nfdt - fdt command"
#endif
#ifdef CONFIG_CONSOLE_TRUETYPE
"\nut font - font command"
"\nfont - font command"
#endif
#ifdef CONFIG_CMD_LOADM
"\nloadm - loadm command parameters and loading memory blob"

View file

@ -221,7 +221,8 @@ static int dm_test_acpi_create_dmar(struct unit_test_state *uts)
ut_assertnonnull(cpu);
ut_assertok(acpi_create_dmar(&dmar, DMAR_INTR_REMAP));
ut_asserteq(DMAR_INTR_REMAP, dmar.flags);
ut_asserteq(32 - 1, dmar.host_address_width);
ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1,
dmar.host_address_width);
return 0;
}
@ -277,13 +278,16 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts)
*/
ut_asserteq_ptr(dmar + 3, ctx.current);
ut_asserteq(DMAR_INTR_REMAP, dmar->flags);
ut_asserteq(32 - 1, dmar->host_address_width);
ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1,
dmar->host_address_width);
ut_asserteq(DMAR_INTR_REMAP, dmar[1].flags);
ut_asserteq(32 - 1, dmar[1].host_address_width);
ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1,
dmar[1].host_address_width);
ut_asserteq(DMAR_INTR_REMAP, dmar[2].flags);
ut_asserteq(32 - 1, dmar[2].host_address_width);
ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1,
dmar[2].host_address_width);
/* Check that the pointers were added correctly */
for (i = 0; i < 3; i++) {