FAT: get_cluster: Add buffer bouncing
authorBenoît Thébaudeau <benoit.thebaudeau@advansee.com>
Fri, 20 Jul 2012 13:21:08 +0000 (15:21 +0200)
committerWolfgang Denk <wd@denx.de>
Sun, 2 Sep 2012 15:22:10 +0000 (17:22 +0200)
Add a buffer bouncing mechanism to get_cluster.  This can be useful
for misaligned applicative buffers passed through get_contents.
This is required for the following patches in the case of data
aligned differently relatively to buffers and clusters.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
Cc: Wolfgang Denk <wd@denx.de>
fs/fat/fat.c

index fbc2d7de1116df199ccc1130127f67456ea835da..fa977b35cb71cfbfe8e0fcef9324112e8530fba2 100644 (file)
@@ -273,7 +273,6 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
 {
        __u32 idx = 0;
        __u32 startsect;
-       __u32 nr_sect;
        int ret;
 
        if (clustnum > 0) {
@@ -285,25 +284,44 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
 
        debug("gc - clustnum: %d, startsect: %d\n", clustnum, startsect);
 
-       nr_sect = size / mydata->sect_size;
-       ret = disk_read(startsect, nr_sect, buffer);
-       if (ret != nr_sect) {
-               debug("Error reading data (got %d)\n", ret);
-               return -1;
-       }
-       if (size % mydata->sect_size) {
+       if ((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1)) {
                ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
 
+               printf("FAT: Misaligned buffer address (%p)\n", buffer);
+
+               while (size >= mydata->sect_size) {
+                       ret = disk_read(startsect++, 1, tmpbuf);
+                       if (ret != 1) {
+                               debug("Error reading data (got %d)\n", ret);
+                               return -1;
+                       }
+
+                       memcpy(buffer, tmpbuf, mydata->sect_size);
+                       buffer += mydata->sect_size;
+                       size -= mydata->sect_size;
+               }
+       } else {
                idx = size / mydata->sect_size;
-               ret = disk_read(startsect + idx, 1, tmpbuf);
+               ret = disk_read(startsect, idx, buffer);
+               if (ret != idx) {
+                       debug("Error reading data (got %d)\n", ret);
+                       return -1;
+               }
+               startsect += idx;
+               idx *= mydata->sect_size;
+               buffer += idx;
+               size -= idx;
+       }
+       if (size) {
+               ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
+
+               ret = disk_read(startsect, 1, tmpbuf);
                if (ret != 1) {
                        debug("Error reading data (got %d)\n", ret);
                        return -1;
                }
-               buffer += idx * mydata->sect_size;
 
-               memcpy(buffer, tmpbuf, size % mydata->sect_size);
-               return 0;
+               memcpy(buffer, tmpbuf, size);
        }
 
        return 0;