u-boot/fs/ext2/dev.c
Anton staaf 4c1cd721d8 ext2: Cache line aligned partial sector bounce buffer
Currently, if a device read request is done that does not begin or end
on a sector boundary a stack allocated bounce buffer is used to perform
the read, and then just the part of the sector that is needed is copied
into the users buffer.  This stack allocation can mean that the bounce
buffer will not be aligned to the dcache line size.  This is a problem
when caches are enabled because unaligned cache invalidates are not
safe.

This patch uses ALLOC_CACHE_ALIGN_BUFFER to create a stack allocated
cache line size aligned bounce buffer.

Signed-off-by: Anton Staaf <robotboy@chromium.org>
Cc: Lukasz Majewski <l.majewski@samsung.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Dave Liu <r63238@freescale.com>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Albert ARIBAUD <albert.u.boot@aribaud.net>

Change-Id: I32e1594d90ef039137bb219b0f7ced55768744ff
Acked-by: Mike Frysinger <vapier@gentoo.org>
2011-10-25 09:25:41 +02:00

131 lines
3.5 KiB
C

/*
* (C) Copyright 2004
* esd gmbh <www.esd-electronics.com>
* Reinhard Arlt <reinhard.arlt@esd-electronics.com>
*
* based on code of fs/reiserfs/dev.c by
*
* (C) Copyright 2003 - 2004
* Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <common.h>
#include <config.h>
#include <ext2fs.h>
static block_dev_desc_t *ext2fs_block_dev_desc;
static disk_partition_t part_info;
int ext2fs_set_blk_dev(block_dev_desc_t *rbdd, int part)
{
ext2fs_block_dev_desc = rbdd;
if (part == 0) {
/* disk doesn't use partition table */
part_info.start = 0;
part_info.size = rbdd->lba;
part_info.blksz = rbdd->blksz;
} else {
if (get_partition_info
(ext2fs_block_dev_desc, part, &part_info)) {
return 0;
}
}
return part_info.size;
}
int ext2fs_devread(int sector, int byte_offset, int byte_len, char *buf)
{
ALLOC_CACHE_ALIGN_BUFFER(char, sec_buf, SECTOR_SIZE);
unsigned sectors;
/*
* Check partition boundaries
*/
if ((sector < 0) ||
((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) >=
part_info.size)) {
/* errnum = ERR_OUTSIDE_PART; */
printf(" ** %s read outside partition sector %d\n",
__func__,
sector);
return 0;
}
/*
* Get the read to the beginning of a partition.
*/
sector += byte_offset >> SECTOR_BITS;
byte_offset &= SECTOR_SIZE - 1;
debug(" <%d, %d, %d>\n", sector, byte_offset, byte_len);
if (ext2fs_block_dev_desc == NULL) {
printf(" ** %s Invalid Block Device Descriptor (NULL)\n",
__func__);
return 0;
}
if (byte_offset != 0) {
/* read first part which isn't aligned with start of sector */
if (ext2fs_block_dev_desc->
block_read(ext2fs_block_dev_desc->dev,
part_info.start + sector, 1,
(unsigned long *) sec_buf) != 1) {
printf(" ** %s read error **\n", __func__);
return 0;
}
memcpy(buf, sec_buf + byte_offset,
min(SECTOR_SIZE - byte_offset, byte_len));
buf += min(SECTOR_SIZE - byte_offset, byte_len);
byte_len -= min(SECTOR_SIZE - byte_offset, byte_len);
sector++;
}
/* read sector aligned part */
sectors = byte_len / SECTOR_SIZE;
if (sectors > 0) {
if (ext2fs_block_dev_desc->block_read(
ext2fs_block_dev_desc->dev,
part_info.start + sector,
sectors,
(unsigned long *) buf) != sectors) {
printf(" ** %s read error - block\n", __func__);
return 0;
}
buf += sectors * SECTOR_SIZE;
byte_len -= sectors * SECTOR_SIZE;
sector += sectors;
}
if (byte_len != 0) {
/* read rest of data which are not in whole sector */
if (ext2fs_block_dev_desc->
block_read(ext2fs_block_dev_desc->dev,
part_info.start + sector, 1,
(unsigned long *) sec_buf) != 1) {
printf(" ** %s read error - last part\n", __func__);
return 0;
}
memcpy(buf, sec_buf, byte_len);
}
return 1;
}