aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorMichal Nazarewicz <m.nazarewicz@samsung.com>2010-03-15 16:38:31 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:32 -0400
commitaae86e8adb3bbf5256eebe76500cf7254365753c (patch)
treecda96346b81f6c9cc807cb697f0ef9aa4d3db778 /drivers/usb/gadget
parentddb495d4d81dee4fdd96ae397d60ddefd65204c6 (diff)
USB: f_mass_storage: dynamic buffers for better alignment
"Static" buffers in fsg_buffhd structure (ie. fields which are arrays rather then pointers to dynamically allocated memory) are not aligned to any "big" power of two which may lead to poor DMA performance (copying "by hand" of head or tail) or no DMA at all even if otherwise hardware supports it. Therefore, this patch makes mass storage function use kmalloc()ed buffers which are (because of their size) page aligned (which should be enough for any hardware). Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com> Cc: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/f_mass_storage.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index f4911c09022e..218f51db9721 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -302,7 +302,6 @@ static const char fsg_string_interface[] = "Mass Storage";
302 302
303 303
304#define FSG_NO_INTR_EP 1 304#define FSG_NO_INTR_EP 1
305#define FSG_BUFFHD_STATIC_BUFFER 1
306#define FSG_NO_DEVICE_STRINGS 1 305#define FSG_NO_DEVICE_STRINGS 1
307#define FSG_NO_OTG 1 306#define FSG_NO_OTG 1
308#define FSG_NO_INTR_EP 1 307#define FSG_NO_INTR_EP 1
@@ -2762,13 +2761,19 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
2762 2761
2763 2762
2764 /* Data buffers cyclic list */ 2763 /* Data buffers cyclic list */
2765 /* Buffers in buffhds are static -- no need for additional
2766 * allocation. */
2767 bh = common->buffhds; 2764 bh = common->buffhds;
2768 i = FSG_NUM_BUFFERS - 1; 2765 i = FSG_NUM_BUFFERS;
2766 goto buffhds_first_it;
2769 do { 2767 do {
2770 bh->next = bh + 1; 2768 bh->next = bh + 1;
2771 } while (++bh, --i); 2769 ++bh;
2770buffhds_first_it:
2771 bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL);
2772 if (unlikely(!bh->buf)) {
2773 rc = -ENOMEM;
2774 goto error_release;
2775 }
2776 } while (--i);
2772 bh->next = common->buffhds; 2777 bh->next = common->buffhds;
2773 2778
2774 2779
@@ -2871,6 +2876,7 @@ static void fsg_common_release(struct kref *ref)
2871 container_of(ref, struct fsg_common, ref); 2876 container_of(ref, struct fsg_common, ref);
2872 unsigned i = common->nluns; 2877 unsigned i = common->nluns;
2873 struct fsg_lun *lun = common->luns; 2878 struct fsg_lun *lun = common->luns;
2879 struct fsg_buffhd *bh;
2874 2880
2875 /* If the thread isn't already dead, tell it to exit now */ 2881 /* If the thread isn't already dead, tell it to exit now */
2876 if (common->state != FSG_STATE_TERMINATED) { 2882 if (common->state != FSG_STATE_TERMINATED) {
@@ -2892,6 +2898,13 @@ static void fsg_common_release(struct kref *ref)
2892 } 2898 }
2893 2899
2894 kfree(common->luns); 2900 kfree(common->luns);
2901
2902 i = FSG_NUM_BUFFERS;
2903 bh = common->buffhds;
2904 do {
2905 kfree(bh->buf);
2906 } while (++bh, --i);
2907
2895 if (common->free_storage_on_release) 2908 if (common->free_storage_on_release)
2896 kfree(common); 2909 kfree(common);
2897} 2910}