diff options
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
| -rw-r--r-- | drivers/usb/class/cdc-acm.c | 22 | 
1 files changed, 10 insertions, 12 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 991786876dbb..7f6f3ab5b8a6 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -378,21 +378,19 @@ static void acm_ctrl_irq(struct urb *urb)  	if (current_size < expected_size) {  		/* notification is transmitted fragmented, reassemble */  		if (acm->nb_size < expected_size) { -			if (acm->nb_size) { -				kfree(acm->notification_buffer); -				acm->nb_size = 0; -			} +			u8 *new_buffer;  			alloc_size = roundup_pow_of_two(expected_size); -			/* -			 * kmalloc ensures a valid notification_buffer after a -			 * use of kfree in case the previous allocation was too -			 * small. Final freeing is done on disconnect. -			 */ -			acm->notification_buffer = -				kmalloc(alloc_size, GFP_ATOMIC); -			if (!acm->notification_buffer) +			/* Final freeing is done on disconnect. */ +			new_buffer = krealloc(acm->notification_buffer, +					      alloc_size, GFP_ATOMIC); +			if (!new_buffer) { +				acm->nb_index = 0;  				goto exit; +			} + +			acm->notification_buffer = new_buffer;  			acm->nb_size = alloc_size; +			dr = (struct usb_cdc_notification *)acm->notification_buffer;  		}  		copy_size = min(current_size,  |