Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 280776
b: refs/heads/master
c: 3f5eb8d
h: refs/heads/master
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Nov 18, 2011
1 parent 5cde7c8 commit 31107c9
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: add1aaeabe6b08ed26381a2a06e505b2f09c3ba5
refs/heads/master: 3f5eb8d5688a5266ab943cf94aebe4c0eea726a3
4 changes: 4 additions & 0 deletions trunk/Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2632,6 +2632,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
[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).
Expand Down
26 changes: 22 additions & 4 deletions trunk/drivers/usb/core/devio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -907,7 +925,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
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)
Expand Down Expand Up @@ -1227,7 +1245,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
return -EINVAL;
}

if (uurb->buffer_length > MAX_USBFS_MEMORY_USAGE) {
if (uurb->buffer_length >= USBFS_XFER_MAX) {
ret = -EINVAL;
goto error;
}
Expand Down

0 comments on commit 31107c9

Please sign in to comment.