diff options
Diffstat (limited to 'drivers/usb/usbip/stub_main.c')
| -rw-r--r-- | drivers/usb/usbip/stub_main.c | 57 | 
1 files changed, 42 insertions, 15 deletions
diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c index 2e4bfccd4bfc..c1c0bbc9f8b1 100644 --- a/drivers/usb/usbip/stub_main.c +++ b/drivers/usb/usbip/stub_main.c @@ -6,6 +6,7 @@  #include <linux/string.h>  #include <linux/module.h>  #include <linux/device.h> +#include <linux/scatterlist.h>  #include "usbip_common.h"  #include "stub.h" @@ -281,13 +282,49 @@ static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead)  	struct stub_priv *priv, *tmp;  	list_for_each_entry_safe(priv, tmp, listhead, list) { -		list_del(&priv->list); +		list_del_init(&priv->list);  		return priv;  	}  	return NULL;  } +void stub_free_priv_and_urb(struct stub_priv *priv) +{ +	struct urb *urb; +	int i; + +	for (i = 0; i < priv->num_urbs; i++) { +		urb = priv->urbs[i]; + +		if (!urb) +			return; + +		kfree(urb->setup_packet); +		urb->setup_packet = NULL; + + +		if (urb->transfer_buffer && !priv->sgl) { +			kfree(urb->transfer_buffer); +			urb->transfer_buffer = NULL; +		} + +		if (urb->num_sgs) { +			sgl_free(urb->sg); +			urb->sg = NULL; +			urb->num_sgs = 0; +		} + +		usb_free_urb(urb); +	} +	if (!list_empty(&priv->list)) +		list_del(&priv->list); +	if (priv->sgl) +		sgl_free(priv->sgl); +	kfree(priv->urbs); +	kmem_cache_free(stub_priv_cache, priv); +} +  static struct stub_priv *stub_priv_pop(struct stub_device *sdev)  {  	unsigned long flags; @@ -314,25 +351,15 @@ done:  void stub_device_cleanup_urbs(struct stub_device *sdev)  {  	struct stub_priv *priv; -	struct urb *urb; +	int i;  	dev_dbg(&sdev->udev->dev, "Stub device cleaning up urbs\n");  	while ((priv = stub_priv_pop(sdev))) { -		urb = priv->urb; -		dev_dbg(&sdev->udev->dev, "free urb seqnum %lu\n", -			priv->seqnum); -		usb_kill_urb(urb); - -		kmem_cache_free(stub_priv_cache, priv); +		for (i = 0; i < priv->num_urbs; i++) +			usb_kill_urb(priv->urbs[i]); -		kfree(urb->transfer_buffer); -		urb->transfer_buffer = NULL; - -		kfree(urb->setup_packet); -		urb->setup_packet = NULL; - -		usb_free_urb(urb); +		stub_free_priv_and_urb(priv);  	}  }  |