Commit a3f2ed17 authored by Duncan Sands's avatar Duncan Sands Committed by Greg Kroah-Hartman

[PATCH] USB: simplify speedtouch receive urb lifecycle

  speedtouch: simplify the receive urb lifecycle: allocate them in the usb probe function,
  free them on disconnect.
parent c0cebfa4
...@@ -688,18 +688,6 @@ static int udsl_usb_data_init (struct udsl_instance_data *instance) ...@@ -688,18 +688,6 @@ static int udsl_usb_data_init (struct udsl_instance_data *instance)
for (i = 0, succes = 0; i < UDSL_NUMBER_RCV_URBS; i++) { for (i = 0, succes = 0; i < UDSL_NUMBER_RCV_URBS; i++) {
struct udsl_data_ctx *ctx = &(instance->rcvbufs[i]); struct udsl_data_ctx *ctx = &(instance->rcvbufs[i]);
ctx->urb = NULL;
ctx->skb = dev_alloc_skb (UDSL_RECEIVE_BUFFER_SIZE);
if (!ctx->skb)
continue;
ctx->urb = usb_alloc_urb (0, GFP_KERNEL);
if (!ctx->urb) {
kfree_skb (ctx->skb);
ctx->skb = NULL;
break;
};
usb_fill_bulk_urb (ctx->urb, usb_fill_bulk_urb (ctx->urb,
instance->usb_dev, instance->usb_dev,
usb_rcvbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_IN), usb_rcvbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_IN),
...@@ -707,12 +695,6 @@ static int udsl_usb_data_init (struct udsl_instance_data *instance) ...@@ -707,12 +695,6 @@ static int udsl_usb_data_init (struct udsl_instance_data *instance)
UDSL_RECEIVE_BUFFER_SIZE, UDSL_RECEIVE_BUFFER_SIZE,
udsl_usb_data_receive, ctx); udsl_usb_data_receive, ctx);
ctx->instance = instance;
PDEBUG ("udsl_usb_data_init: usb with skb->truesize = %d (Asked for %d)\n",
ctx->skb->truesize, UDSL_RECEIVE_BUFFER_SIZE);
if (usb_submit_urb (ctx->urb, GFP_KERNEL) < 0) if (usb_submit_urb (ctx->urb, GFP_KERNEL) < 0)
PDEBUG ("udsl_usb_data_init: Submit failed, loosing urb.\n"); PDEBUG ("udsl_usb_data_init: Submit failed, loosing urb.\n");
else else
...@@ -753,10 +735,6 @@ static int udsl_usb_data_exit (struct udsl_instance_data *instance) ...@@ -753,10 +735,6 @@ static int udsl_usb_data_exit (struct udsl_instance_data *instance)
continue; continue;
usb_unlink_urb (ctx->urb); usb_unlink_urb (ctx->urb);
usb_free_urb (ctx->urb);
kfree_skb (ctx->skb);
ctx->skb = NULL;
} }
tasklet_kill (&instance->recvqueue_tasklet); tasklet_kill (&instance->recvqueue_tasklet);
...@@ -842,6 +820,27 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i ...@@ -842,6 +820,27 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
tasklet_init (&instance->recvqueue_tasklet, udsl_atm_processqueue, (unsigned long) instance); tasklet_init (&instance->recvqueue_tasklet, udsl_atm_processqueue, (unsigned long) instance);
/* receive urb init */
for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) {
struct udsl_data_ctx *ctx = &(instance->rcvbufs[i]);
if (!(ctx->skb = dev_alloc_skb (UDSL_RECEIVE_BUFFER_SIZE))) {
PDEBUG ("No memory for skb %d!\n", i);
err = -ENOMEM;
goto fail_urbs;
}
if (!(ctx->urb = usb_alloc_urb (0, GFP_KERNEL))) {
PDEBUG ("No memory for receive urb %d!\n", i);
err = -ENOMEM;
goto fail_urbs;
}
ctx->instance = instance;
PDEBUG ("skb->truesize = %d (asked for %d)\n", ctx->skb->truesize, UDSL_RECEIVE_BUFFER_SIZE);
}
/* atm init */ /* atm init */
if (!(instance->atm_dev = atm_dev_register (udsl_driver_name, &udsl_atm_devops, -1, 0))) { if (!(instance->atm_dev = atm_dev_register (udsl_driver_name, &udsl_atm_devops, -1, 0))) {
PDEBUG ("failed to register ATM device!\n"); PDEBUG ("failed to register ATM device!\n");
...@@ -874,6 +873,16 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i ...@@ -874,6 +873,16 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
return 0; return 0;
fail_atm: fail_atm:
fail_urbs:
for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) {
struct udsl_data_ctx *ctx = &(instance->rcvbufs[i]);
if (ctx->skb)
kfree_skb (ctx->skb);
if (ctx->urb)
usb_free_urb (ctx->urb);
}
kfree (instance); kfree (instance);
fail_instance: fail_instance:
return err; return err;
...@@ -882,20 +891,32 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i ...@@ -882,20 +891,32 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
static void udsl_usb_disconnect (struct usb_interface *intf) static void udsl_usb_disconnect (struct usb_interface *intf)
{ {
struct udsl_instance_data *instance = usb_get_intfdata (intf); struct udsl_instance_data *instance = usb_get_intfdata (intf);
int i;
PDEBUG ("disconnecting\n"); PDEBUG ("disconnecting\n");
usb_set_intfdata (intf, NULL); usb_set_intfdata (intf, NULL);
if (instance) {
if (!instance) {
PDEBUG ("NULL instance!\n");
return;
}
/* unlinking receive buffers */ /* unlinking receive buffers */
udsl_usb_data_exit (instance); udsl_usb_data_exit (instance);
for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) {
struct udsl_data_ctx *ctx = &(instance->rcvbufs[i]);
usb_free_urb (ctx->urb);
kfree_skb (ctx->skb);
}
/* removing atm device */ /* removing atm device */
if (instance->atm_dev) if (instance->atm_dev)
udsl_atm_stopdevice (instance); udsl_atm_stopdevice (instance);
kfree (instance); kfree (instance);
}
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment