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:
parent
7c44444883
commit
c620b321b1
2
arch
2
arch
@ -1 +1 @@
|
||||
Subproject commit 7ed1d2eb50bcfc637e21fcf41521e562d4a521a1
|
||||
Subproject commit 50415398b1ae76ffb66df9813f4647dcbfcee234
|
@ -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
|
||||
|
@ -410,16 +410,15 @@ static int fat_close(FAR struct file *filep)
|
||||
/* Recover our private data from the struct file instance */
|
||||
|
||||
ff = filep->f_priv;
|
||||
|
||||
/* Check for the forced mount condition */
|
||||
|
||||
if ((ff->ff_bflags & UMOUNT_FORCED) == 0)
|
||||
{
|
||||
inode = filep->f_inode;
|
||||
fs = inode->i_private;
|
||||
|
||||
DEBUGASSERT(fs != NULL);
|
||||
|
||||
/* Check for the forced mount condition */
|
||||
|
||||
if ((ff->ff_bflags & UMOUNT_FORCED) == 0)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user