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.
|
hardware RTC or other way to get the time and date.
|
||||||
|
|
||||||
config FAT_FORCE_INDIRECT
|
config FAT_FORCE_INDIRECT
|
||||||
bool "Force all in-direct transfers"
|
bool "Force direct transfers"
|
||||||
default n
|
default n
|
||||||
---help---
|
---help---
|
||||||
Normally, the default behavior for the FAT file system is to perform
|
Normally, the default behavior for the FAT file system is to perform
|
||||||
data transfers indirectly though specially allocated sector buffers
|
data transfers indirectly though specially allocated sector buffers
|
||||||
or, under certain circumstances, directly through user provided
|
or, under certain circumstances, directly through user provided
|
||||||
@ -73,9 +73,20 @@ default n
|
|||||||
systems internal sector buffers, and (2) A loss of performance
|
systems internal sector buffers, and (2) A loss of performance
|
||||||
because I/O will be limited to one sector at a time.
|
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
|
config FAT_DMAMEMORY
|
||||||
bool "DMA memory allocator"
|
bool "DMA memory allocator"
|
||||||
default n
|
default n
|
||||||
|
select FAT_DIRECT_RETRY if !FAT_FORCE_INDIRECT
|
||||||
---help---
|
---help---
|
||||||
The FAT file system allocates two I/O buffers for data transfer, each
|
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
|
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
|
corresponding function that will be called to free the DMA-capable
|
||||||
memory.
|
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
|
endif # FAT
|
||||||
|
@ -410,16 +410,15 @@ static int fat_close(FAR struct file *filep)
|
|||||||
/* Recover our private data from the struct file instance */
|
/* Recover our private data from the struct file instance */
|
||||||
|
|
||||||
ff = filep->f_priv;
|
ff = filep->f_priv;
|
||||||
|
|
||||||
/* Check for the forced mount condition */
|
|
||||||
|
|
||||||
if ((ff->ff_bflags & UMOUNT_FORCED) == 0)
|
|
||||||
{
|
|
||||||
inode = filep->f_inode;
|
inode = filep->f_inode;
|
||||||
fs = inode->i_private;
|
fs = inode->i_private;
|
||||||
|
|
||||||
DEBUGASSERT(fs != NULL);
|
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
|
/* Do not check if the mount is healthy. We must support closing of
|
||||||
* the file even when there is healthy mount.
|
* 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;
|
ff->ff_sectorsincluster = fs->fs_fatsecperclus;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_FAT_DMAMEMORY /* Warning avoidance */
|
#ifdef CONFIG_FAT_DIRECT_RETRY /* Warning avoidance */
|
||||||
fat_read_restart:
|
fat_read_restart:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -626,21 +625,22 @@ fat_read_restart:
|
|||||||
ret = fat_hwread(fs, userbuffer, ff->ff_currentsector, nsectors);
|
ret = fat_hwread(fs, userbuffer, ff->ff_currentsector, nsectors);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_FAT_DMAMEMORY
|
#ifdef CONFIG_FAT_DIRECT_RETRY
|
||||||
/* The low-level driver may return -EFAULT in the case where
|
/* The low-level driver may return -EFAULT in the case where
|
||||||
* the transfer cannot be performed due to DMA constraints.
|
* the transfer cannot be performed due to buffer memory
|
||||||
* It is probable that the buffer is completely un-DMA-able,
|
* constraints. It is probable that the buffer is completely
|
||||||
* so force indirect transfers via the sector buffer and
|
* un-DMA-able or improperly aligned. In this case, force
|
||||||
* restart the operation.
|
* 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");
|
fdbg("DMA: read alignment error, restarting indirect\n");
|
||||||
force_indirect = true;
|
force_indirect = true;
|
||||||
goto fat_read_restart;
|
goto fat_read_restart;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_FAT_DMAMEMORY */
|
#endif /* CONFIG_FAT_DIRECT_RETRY */
|
||||||
|
|
||||||
goto errout_with_semaphore;
|
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);
|
ff->ff_currentsector = fat_cluster2sector(fs, cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_FAT_DMAMEMORY /* Warning avoidance */
|
#ifdef CONFIG_FAT_DIRECT_RETRY /* Warning avoidance */
|
||||||
fat_write_restart:
|
fat_write_restart:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -885,21 +885,22 @@ fat_write_restart:
|
|||||||
ret = fat_hwwrite(fs, userbuffer, ff->ff_currentsector, nsectors);
|
ret = fat_hwwrite(fs, userbuffer, ff->ff_currentsector, nsectors);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_FAT_DMAMEMORY
|
#ifdef CONFIG_FAT_DIRECT_RETRY
|
||||||
/* The low-level driver may return -EFAULT in the case where
|
/* The low-level driver may return -EFAULT in the case where
|
||||||
* the transfer cannot be performed due to DMA constraints.
|
* the transfer cannot be performed due to buffer memory
|
||||||
* It is probable that the buffer is completely un-DMA-able,
|
* constraints. It is probable that the buffer is completely
|
||||||
* so force indirect transfers via the sector buffer and
|
* un-DMA-able or improperly aligned. In this case, force
|
||||||
* restart the operation.
|
* 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");
|
fdbg("DMA: write alignment error, restarting indirect\n");
|
||||||
force_indirect = true;
|
force_indirect = true;
|
||||||
goto fat_write_restart;
|
goto fat_write_restart;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_FAT_DMAMEMORY */
|
#endif /* CONFIG_FAT_DIRECT_RETRY */
|
||||||
|
|
||||||
goto errout_with_semaphore;
|
goto errout_with_semaphore;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user