FAT: Add a new configuration option to decouple the logic that retries the direct transfer from the logic that enables DMA memory allocators.

This commit is contained in:
Gregory Nutt 2016-02-22 18:25:58 -06:00
parent 7c44444883
commit c620b321b1
3 changed files with 66 additions and 26 deletions

2
arch

@ -1 +1 @@
Subproject commit 7ed1d2eb50bcfc637e21fcf41521e562d4a521a1
Subproject commit 50415398b1ae76ffb66df9813f4647dcbfcee234

View File

@ -51,9 +51,9 @@ config FS_FATTIME
hardware RTC or other way to get the time and date.
config FAT_FORCE_INDIRECT
bool "Force all in-direct transfers"
default n
---help---
bool "Force direct transfers"
default n
---help---
Normally, the default behavior for the FAT file system is to perform
data transfers indirectly though specially allocated sector buffers
or, under certain circumstances, directly through user provided
@ -73,9 +73,20 @@ default n
systems internal sector buffers, and (2) A loss of performance
because I/O will be limited to one sector at a time.
This would typically be used with CONFIG_FAT_DMAMEMORY so that
special memory allocators are also used and transfers are also
performed using only that specially allocated memory.
CONFIG_FAT_DMAMEMORY, on the other hand, is often used without
CONFIG_FAT_FORCE_INDIRECT when the user memory buffers may come
from mixed locations, some of which are DMA-able and some of
which are not. But CONFIG_FAT_FORCE_INDIRECT could be used
without CONFIG_FAT_DMAMEMORY if there is, for example, only a
memory aligment constraints.
config FAT_DMAMEMORY
bool "DMA memory allocator"
default n
select FAT_DIRECT_RETRY if !FAT_FORCE_INDIRECT
---help---
The FAT file system allocates two I/O buffers for data transfer, each
are the size of one device sector. One of the buffers is allocated
@ -90,4 +101,32 @@ config FAT_DMAMEMORY
corresponding function that will be called to free the DMA-capable
memory.
config FAT_DIRECT_RETRY
bool "Direct transfer retry"
default y if FAT_DMAMEMORY
default n if !FAT_DMAMEMORY
depends on !FAT_FORCE_INDIRECT
---help---
The FAT file system contains internal, well aligned sector buffers
for indirect data transfer. These transfers are indirect in the
sense that that the actual transfer occurs into/out of the sector
buffers and an additional copy is necessary to/from the user-
provided I/O buffers. But under certain conditions, the FAT file
system will use the caller-provided I/O buffers directly to improve
efficiency. Those conditions are (1) CONFIG_FAT_FORCE_INDIRECT is
not defined, (2) The access is to/from the beginning of a sector,
and (3) the user provided buffer is large enough to hold an entire
sector.
The lower level SDIO driver may have, certain requirements on the
memory buffer in order to perform the transfer. Perhaps special
DMA memory should be used (with CONFIG_FAT_DMAMEMORY) or perhaps
some special memory alignment is required to interace with the
hardware.
If this option is selected, then the FAT file system will first
try the user provided I/O buffer under above conditions. If the
transfer fails with -EFAULT. then the FAT file system will try one
more time using the internal sector buffers.
endif # FAT

View File

@ -409,17 +409,16 @@ static int fat_close(FAR struct file *filep)
/* Recover our private data from the struct file instance */
ff = filep->f_priv;
ff = filep->f_priv;
inode = filep->f_inode;
fs = inode->i_private;
DEBUGASSERT(fs != NULL);
/* Check for the forced mount condition */
if ((ff->ff_bflags & UMOUNT_FORCED) == 0)
{
inode = filep->f_inode;
fs = inode->i_private;
DEBUGASSERT(fs != NULL);
/* Do not check if the mount is healthy. We must support closing of
* the file even when there is healthy mount.
*/
@ -589,7 +588,7 @@ static ssize_t fat_read(FAR struct file *filep, FAR char *buffer,
ff->ff_sectorsincluster = fs->fs_fatsecperclus;
}
#ifdef CONFIG_FAT_DMAMEMORY /* Warning avoidance */
#ifdef CONFIG_FAT_DIRECT_RETRY /* Warning avoidance */
fat_read_restart:
#endif
@ -626,21 +625,22 @@ fat_read_restart:
ret = fat_hwread(fs, userbuffer, ff->ff_currentsector, nsectors);
if (ret < 0)
{
#ifdef CONFIG_FAT_DMAMEMORY
#ifdef CONFIG_FAT_DIRECT_RETRY
/* The low-level driver may return -EFAULT in the case where
* the transfer cannot be performed due to DMA constraints.
* It is probable that the buffer is completely un-DMA-able,
* so force indirect transfers via the sector buffer and
* restart the operation.
* the transfer cannot be performed due to buffer memory
* constraints. It is probable that the buffer is completely
* un-DMA-able or improperly aligned. In this case, force
* indirect transfers via the sector buffer and restart the
* operation (unless we have already tried that).
*/
if (ret == -EFAULT)
if (ret == -EFAULT && !force_indirect)
{
fdbg("DMA: read alignment error, restarting indirect\n");
force_indirect = true;
goto fat_read_restart;
}
#endif /* CONFIG_FAT_DMAMEMORY */
#endif /* CONFIG_FAT_DIRECT_RETRY */
goto errout_with_semaphore;
}
@ -848,7 +848,7 @@ static ssize_t fat_write(FAR struct file *filep, FAR const char *buffer,
ff->ff_currentsector = fat_cluster2sector(fs, cluster);
}
#ifdef CONFIG_FAT_DMAMEMORY /* Warning avoidance */
#ifdef CONFIG_FAT_DIRECT_RETRY /* Warning avoidance */
fat_write_restart:
#endif
@ -885,21 +885,22 @@ fat_write_restart:
ret = fat_hwwrite(fs, userbuffer, ff->ff_currentsector, nsectors);
if (ret < 0)
{
#ifdef CONFIG_FAT_DMAMEMORY
#ifdef CONFIG_FAT_DIRECT_RETRY
/* The low-level driver may return -EFAULT in the case where
* the transfer cannot be performed due to DMA constraints.
* It is probable that the buffer is completely un-DMA-able,
* so force indirect transfers via the sector buffer and
* restart the operation.
* the transfer cannot be performed due to buffer memory
* constraints. It is probable that the buffer is completely
* un-DMA-able or improperly aligned. In this case, force
* indirect transfers via the sector buffer and restart the
* operation (unless we have already tried that).
*/
if (ret == -EFAULT)
if (ret == -EFAULT && !force_indirect)
{
fdbg("DMA: write alignment error, restarting indirect\n");
force_indirect = true;
goto fat_write_restart;
}
#endif /* CONFIG_FAT_DMAMEMORY */
#endif /* CONFIG_FAT_DIRECT_RETRY */
goto errout_with_semaphore;
}