Skip to content

Commit 1129d27

Browse files
mateuszbgregkh
authored andcommitted
USB: Increase usbfs transfer limit
Promote a variable keeping track of USB transfer memory usage to a wider data type and allow for higher bandwidth transfers from a large number of USB devices connected to a single host. Signed-off-by: Mateusz Berezecki <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 444d930 commit 1129d27

File tree

1 file changed

+16
-27
lines changed

1 file changed

+16
-27
lines changed

drivers/usb/core/devio.c

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -134,42 +134,35 @@ enum snoop_when {
134134
#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0)
135135

136136
/* Limit on the total amount of memory we can allocate for transfers */
137-
static unsigned usbfs_memory_mb = 16;
137+
static u32 usbfs_memory_mb = 16;
138138
module_param(usbfs_memory_mb, uint, 0644);
139139
MODULE_PARM_DESC(usbfs_memory_mb,
140140
"maximum MB allowed for usbfs buffers (0 = no limit)");
141141

142-
/* Hard limit, necessary to avoid arithmetic overflow */
143-
#define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000)
144-
145-
static atomic_t usbfs_memory_usage; /* Total memory currently allocated */
142+
static atomic64_t usbfs_memory_usage; /* Total memory currently allocated */
146143

147144
/* Check whether it's okay to allocate more memory for a transfer */
148-
static int usbfs_increase_memory_usage(unsigned amount)
145+
static int usbfs_increase_memory_usage(u64 amount)
149146
{
150-
unsigned lim;
147+
u64 lim;
151148

152-
/*
153-
* Convert usbfs_memory_mb to bytes, avoiding overflows.
154-
* 0 means use the hard limit (effectively unlimited).
155-
*/
156149
lim = ACCESS_ONCE(usbfs_memory_mb);
157-
if (lim == 0 || lim > (USBFS_XFER_MAX >> 20))
158-
lim = USBFS_XFER_MAX;
159-
else
160-
lim <<= 20;
150+
lim <<= 20;
161151

162-
atomic_add(amount, &usbfs_memory_usage);
163-
if (atomic_read(&usbfs_memory_usage) <= lim)
164-
return 0;
165-
atomic_sub(amount, &usbfs_memory_usage);
166-
return -ENOMEM;
152+
atomic64_add(amount, &usbfs_memory_usage);
153+
154+
if (lim > 0 && atomic64_read(&usbfs_memory_usage) > lim) {
155+
atomic64_sub(amount, &usbfs_memory_usage);
156+
return -ENOMEM;
157+
}
158+
159+
return 0;
167160
}
168161

169162
/* Memory for a transfer is being deallocated */
170-
static void usbfs_decrease_memory_usage(unsigned amount)
163+
static void usbfs_decrease_memory_usage(u64 amount)
171164
{
172-
atomic_sub(amount, &usbfs_memory_usage);
165+
atomic64_sub(amount, &usbfs_memory_usage);
173166
}
174167

175168
static int connected(struct usb_dev_state *ps)
@@ -1191,7 +1184,7 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg)
11911184
if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
11921185
return -EINVAL;
11931186
len1 = bulk.len;
1194-
if (len1 >= USBFS_XFER_MAX)
1187+
if (len1 >= (INT_MAX - sizeof(struct urb)))
11951188
return -EINVAL;
11961189
ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
11971190
if (ret)
@@ -1584,10 +1577,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
15841577
return -EINVAL;
15851578
}
15861579

1587-
if (uurb->buffer_length >= USBFS_XFER_MAX) {
1588-
ret = -EINVAL;
1589-
goto error;
1590-
}
15911580
if (uurb->buffer_length > 0 &&
15921581
!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
15931582
uurb->buffer, uurb->buffer_length)) {

0 commit comments

Comments
 (0)