[PATCH 3/3] USB: make the usbfs memory limit configurable

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxxxxxx>

---

 Documentation/kernel-parameters.txt |    4 ++++
 drivers/usb/core/devio.c            |   26 ++++++++++++++++++++++----
 2 files changed, 26 insertions(+), 4 deletions(-)

Index: usb-3.2/Documentation/kernel-parameters.txt
===================================================================
--- usb-3.2.orig/Documentation/kernel-parameters.txt
+++ usb-3.2/Documentation/kernel-parameters.txt
@@ -2632,6 +2632,10 @@ bytes respectively. Such letter suffixes
 			[USB] Start with the old device initialization
 			scheme (default 0 = off).
 
+	usbcore.usbfs_memory_mb=
+			[USB] Memory limit (in MB) for buffers allocated by
+			usbfs (default = 16, 0 = max = 2047).
+
 	usbcore.use_both_schemes=
 			[USB] Try the other device initialization scheme
 			if the first one fails (default 1 = enabled).
Index: usb-3.2/drivers/usb/core/devio.c
===================================================================
--- usb-3.2.orig/drivers/usb/core/devio.c
+++ usb-3.2/drivers/usb/core/devio.c
@@ -110,15 +110,33 @@ enum snoop_when {
 #define USB_DEVICE_DEV		MKDEV(USB_DEVICE_MAJOR, 0)
 
 /* Limit on the total amount of memory we can allocate for transfers */
-#define MAX_USBFS_MEMORY_USAGE	16777216	/* 16 MB */
+static unsigned usbfs_memory_mb = 16;
+module_param(usbfs_memory_mb, uint, 0644);
+MODULE_PARM_DESC(usbfs_memory_mb,
+		"maximum MB allowed for usbfs buffers (0 = no limit)");
+
+/* Hard limit, necessary to avoid aithmetic overflow */
+#define USBFS_XFER_MAX		(UINT_MAX / 2 - 1000000)
 
 static atomic_t usbfs_memory_usage;	/* Total memory currently allocated */
 
 /* Check whether it's okay to allocate more memory for a transfer */
 static int usbfs_increase_memory_usage(unsigned amount)
 {
+	unsigned lim;
+
+	/*
+	 * Convert usbfs_memory_mb to bytes, avoiding overflows.
+	 * 0 means use the hard limit (effectively unlimited).
+	 */
+	lim = ACCESS_ONCE(usbfs_memory_mb);
+	if (lim == 0 || lim > (USBFS_XFER_MAX >> 20))
+		lim = USBFS_XFER_MAX;
+	else
+		lim <<= 20;
+
 	atomic_add(amount, &usbfs_memory_usage);
-	if (atomic_read(&usbfs_memory_usage) <= MAX_USBFS_MEMORY_USAGE)
+	if (atomic_read(&usbfs_memory_usage) <= lim)
 		return 0;
 	atomic_sub(amount, &usbfs_memory_usage);
 	return -ENOMEM;
@@ -907,7 +925,7 @@ static int proc_bulk(struct dev_state *p
 	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
 		return -EINVAL;
 	len1 = bulk.len;
-	if (len1 > MAX_USBFS_MEMORY_USAGE)
+	if (len1 >= USBFS_XFER_MAX)
 		return -EINVAL;
 	ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
 	if (ret)
@@ -1227,7 +1245,7 @@ static int proc_do_submiturb(struct dev_
 		return -EINVAL;
 	}
 
-	if (uurb->buffer_length > MAX_USBFS_MEMORY_USAGE) {
+	if (uurb->buffer_length >= USBFS_XFER_MAX) {
 		ret = -EINVAL;
 		goto error;
 	}

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux