aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2011-11-17 16:41:35 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-11-18 14:09:07 -0500
commit3f5eb8d5688a5266ab943cf94aebe4c0eea726a3 (patch)
treef91c3a0743c1c7058704b20517f4c533c4a6dbb8 /drivers/usb/core
parentadd1aaeabe6b08ed26381a2a06e505b2f09c3ba5 (diff)
USB: make the usbfs memory limit configurable
The 16-MB global limit on memory used by usbfs isn't suitable for all people. It's a reasonable default, but there are applications (especially for SuperSpeed devices) that need a lot more. This patch (as1498) creates a writable module parameter for usbcore to control the global limit. The default is still 16 MB, but users can change it at runtime, even after usbcore has been loaded. As a special case, setting the value to 0 is treated the same as the hard limit of 2047 MB. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/devio.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index b69768b7d226..d8cf06f186f2 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -110,15 +110,33 @@ enum snoop_when {
110#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0) 110#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0)
111 111
112/* Limit on the total amount of memory we can allocate for transfers */ 112/* Limit on the total amount of memory we can allocate for transfers */
113#define MAX_USBFS_MEMORY_USAGE 16777216 /* 16 MB */ 113static unsigned usbfs_memory_mb = 16;
114module_param(usbfs_memory_mb, uint, 0644);
115MODULE_PARM_DESC(usbfs_memory_mb,
116 "maximum MB allowed for usbfs buffers (0 = no limit)");
117
118/* Hard limit, necessary to avoid aithmetic overflow */
119#define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000)
114 120
115static atomic_t usbfs_memory_usage; /* Total memory currently allocated */ 121static atomic_t usbfs_memory_usage; /* Total memory currently allocated */
116 122
117/* Check whether it's okay to allocate more memory for a transfer */ 123/* Check whether it's okay to allocate more memory for a transfer */
118static int usbfs_increase_memory_usage(unsigned amount) 124static int usbfs_increase_memory_usage(unsigned amount)
119{ 125{
126 unsigned lim;
127
128 /*
129 * Convert usbfs_memory_mb to bytes, avoiding overflows.
130 * 0 means use the hard limit (effectively unlimited).
131 */
132 lim = ACCESS_ONCE(usbfs_memory_mb);
133 if (lim == 0 || lim > (USBFS_XFER_MAX >> 20))
134 lim = USBFS_XFER_MAX;
135 else
136 lim <<= 20;
137
120 atomic_add(amount, &usbfs_memory_usage); 138 atomic_add(amount, &usbfs_memory_usage);
121 if (atomic_read(&usbfs_memory_usage) <= MAX_USBFS_MEMORY_USAGE) 139 if (atomic_read(&usbfs_memory_usage) <= lim)
122 return 0; 140 return 0;
123 atomic_sub(amount, &usbfs_memory_usage); 141 atomic_sub(amount, &usbfs_memory_usage);
124 return -ENOMEM; 142 return -ENOMEM;
@@ -907,7 +925,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
907 if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN))) 925 if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
908 return -EINVAL; 926 return -EINVAL;
909 len1 = bulk.len; 927 len1 = bulk.len;
910 if (len1 > MAX_USBFS_MEMORY_USAGE) 928 if (len1 >= USBFS_XFER_MAX)
911 return -EINVAL; 929 return -EINVAL;
912 ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb)); 930 ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
913 if (ret) 931 if (ret)
@@ -1227,7 +1245,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
1227 return -EINVAL; 1245 return -EINVAL;
1228 } 1246 }
1229 1247
1230 if (uurb->buffer_length > MAX_USBFS_MEMORY_USAGE) { 1248 if (uurb->buffer_length >= USBFS_XFER_MAX) {
1231 ret = -EINVAL; 1249 ret = -EINVAL;
1232 goto error; 1250 goto error;
1233 } 1251 }