diff options
Diffstat (limited to 'xpp/xpp_usb.c')
-rw-r--r-- | xpp/xpp_usb.c | 93 |
1 files changed, 57 insertions, 36 deletions
diff --git a/xpp/xpp_usb.c b/xpp/xpp_usb.c index 785e713..796b127 100644 --- a/xpp/xpp_usb.c +++ b/xpp/xpp_usb.c @@ -120,9 +120,9 @@ enum xusb_dir { XUSB_SEND = 1, }; -static int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe); -static int xframe_send_cmd(xbus_t *xbus, xframe_t *xframe); -static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t flags); +static __must_check int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe); +static __must_check int xframe_send_cmd(xbus_t *xbus, xframe_t *xframe); +static __must_check xframe_t *alloc_xframe(xbus_t *xbus, gfp_t flags); static void free_xframe(xbus_t *xbus, xframe_t *frm); static struct xbus_ops xusb_ops = { @@ -206,6 +206,7 @@ struct xusb { int present; /* if the device is not disconnected */ atomic_t pending_writes; /* submited but not out yet */ + atomic_t pending_reads; /* submited but not in yet */ struct semaphore sem; /* locks this structure */ int counters[XUSB_COUNTER_MAX]; @@ -311,7 +312,7 @@ static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags) if(!p) { if((rate_limit++ % 1003) == 0) XUSB_ERR(xusb, "buffer allocation failed (%d)\n", rate_limit); - kfree(uframe); + kmem_cache_free(xusb_cache, uframe); return NULL; } uframe->uframe_magic = UFRAME_MAGIC; @@ -386,13 +387,14 @@ static int do_send_xframe(xbus_t *xbus, xframe_t *xframe) if(ret < 0) { static int rate_limit; - if((rate_limit++ % 1000) < 5) - XUSB_ERR(xusb, "failed submit_urb: %d\n", ret); + if((rate_limit++ % 1000) == 0) + XBUS_ERR(xbus, "%s: usb_submit_urb failed: %d\n", + __FUNCTION__, ret); ret = -EBADF; goto failure; } // if (print_dbg) -// dump_xframe("USB_FRAME_SEND", xbus, xframe); +// dump_xframe("USB_FRAME_SEND", xbus, xframe, print_dbg); atomic_inc(&xusb->pending_writes); return 0; failure: @@ -451,10 +453,15 @@ static bool xusb_listen(xusb_t *xusb) uframe_recompute(uframe, XUSB_RECV); ret = usb_submit_urb(&uframe->urb, GFP_ATOMIC); if(ret < 0) { - XBUS_ERR(xbus, "Failed to submit a receive urb\n"); + static int rate_limit; + + if((rate_limit++ % 1000) == 0) + XBUS_ERR(xbus, "%s: usb_submit_urb failed: %d\n", + __FUNCTION__, ret); FREE_RECV_XFRAME(xbus, xframe); goto out; } + atomic_inc(&xusb->pending_reads); ret = 1; out: put_xbus(xbus); @@ -618,6 +625,17 @@ static int set_endpoints(xusb_t *xusb, struct usb_host_interface *iface_desc, st return 1; } +/* + * The USB stack before 2.6.10 seems to be a bit shoddy. It seems that when + * being called from the probe we may already have the lock to udev (the Usb DEVice). + * Thus we call the internal __usb_reset_device instead. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +#define DO_USB_RESET_DEVICE(dev) __usb_reset_device(dev) +#else +#define DO_USB_RESET_DEVICE(dev) usb_reset_device(dev) +#endif + /** * xusb_probe * @@ -642,15 +660,7 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i iface_desc->desc.bInterfaceNumber, model_info->iface_num); return -ENODEV; } - - /* The USB stack before 2.6.10 seems to be a bit shoddy. It seems that when being called - * from the probe we may already have the lock to udev (the Usb DEVice). Thus we call - * the internal __usb_reset_device instead. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - if((retval = __usb_reset_device(udev)) < 0) { -#else - if((retval = usb_reset_device(udev)) < 0) { -#endif + if((retval = DO_USB_RESET_DEVICE(udev)) < 0) { ERR("usb_reset_device failed: %d\n", retval); goto probe_failed; } @@ -670,6 +680,7 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i } init_MUTEX (&xusb->sem); atomic_set(&xusb->pending_writes, 0); + atomic_set(&xusb->pending_reads, 0); atomic_set(&xusb->pcm_tx_drops, 0); atomic_set(&xusb->usb_sluggish_count, 0); xusb->udev = udev; @@ -727,12 +738,12 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i goto probe_failed; } usb_make_path(udev, xusb->path, XBUS_DESCLEN); // May trunacte... ignore - snprintf(xbus->busdesc, XBUS_DESCLEN, "%s", xusb->path); + snprintf(xbus->location, XBUS_DESCLEN, "%s", xusb->path); if(xusb->serial && xusb->serial[0]) snprintf(xbus->label, LABEL_SIZE, "usb:%s", xusb->serial); xusb->index = i; xusb_array[i] = xusb; - XUSB_DBG(DEVICES, xusb, "GOT XPP USB BUS: %s\n", xbus->busdesc); + XUSB_DBG(DEVICES, xusb, "GOT XPP USB BUS: %s\n", xbus->location); #ifdef CONFIG_PROC_FS DBG(PROC, "Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n"); @@ -748,16 +759,21 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i #endif bus_count++; xusb->xbus_num = xbus->num; - xusb_listen(xusb); + /* prepare several pending frames for receive side */ + for(i = 0; i < 10; i++) + xusb_listen(xusb); xbus_activate(xbus); return retval; probe_failed: ERR("Failed to initialize xpp usb bus: %d\n", retval); usb_set_intfdata (interface, NULL); if(xusb) { - if(xusb->minor) // passed registration phase + if(xusb->minor) { // passed registration phase + ERR("Calling usb_deregister_dev()\n"); usb_deregister_dev(interface, &xusb_class); - kfree(xusb); + } + ERR("Removing failed xusb\n"); + KZFREE(xusb); } if(xbus) { if(procsummary) { @@ -765,6 +781,7 @@ probe_failed: remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir); procsummary = NULL; } + ERR("Calling xbus_disconnect()\n"); xbus_disconnect(xbus); // Blocking until fully deactivated! } return retval; @@ -793,6 +810,7 @@ static void xusb_disconnect(struct usb_interface *interface) down (&disconnect_sem); xusb = usb_get_intfdata (interface); + xusb->present = 0; xbus = get_xbus(xusb->xbus_num); /* find our xusb */ @@ -813,7 +831,6 @@ static void xusb_disconnect(struct usb_interface *interface) * put_xbus() would be called during xbus_disconnect() */ xbus_disconnect(xbus); // Blocking until fully deactivated! - xusb->present = 0; usb_set_intfdata (interface, NULL); down (&xusb->sem); @@ -824,10 +841,10 @@ static void xusb_disconnect(struct usb_interface *interface) up (&xusb->sem); DBG(DEVICES, "Semaphore released\n"); - kfree(xusb); + XUSB_INFO(xusb, "now disconnected\n"); + KZFREE(xusb); up (&disconnect_sem); - XUSB_INFO(xusb, "now disconnected\n"); } static void xpp_send_callback(USB_PASS_CB(urb)) @@ -874,10 +891,12 @@ static void xpp_send_callback(USB_PASS_CB(urb)) /* sync/async unlink faults aren't errors */ if (urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET)) { static int rate_limit; - if((rate_limit++ % 1000) < 10) + if((rate_limit++ % 1000) < 10) { XUSB_ERR(xusb, "nonzero write bulk status received: %d (pending_writes=%d)\n", urb->status, writes); + dump_xframe("usb-write-error", xbus, xframe, DBG_ANY); + } XUSB_COUNTER(xusb, TX_ERRORS)++; } else XUSB_COUNTER(xusb, TX_FRAMES)++; @@ -896,17 +915,14 @@ static void xpp_receive_callback(USB_PASS_CB(urb)) size_t size; bool do_resubmit = 1; bool is_inuse = 0; + struct timeval now; - //flip_parport_bit(7); + do_gettimeofday(&now); + atomic_dec(&xusb->pending_reads); if(!xbus) { XUSB_ERR(xusb, "Received URB does not belong to a valid xbus anymore...\n"); return; } - if (urb->status) { - DBG(GENERAL, "nonzero read bulk status received: %d\n", urb->status); - XUSB_COUNTER(xusb, RX_ERRORS)++; - goto err; - } if(!XBUS_GET(xbus)) { XUSB_ERR(xusb, "Dropping urb. Is shutting down.\n"); do_resubmit = 0; @@ -914,10 +930,14 @@ static void xpp_receive_callback(USB_PASS_CB(urb)) } is_inuse = 1; if(!xusb->present) { - XUSB_ERR(xusb, "A packet from non-connected device?\n"); do_resubmit = 0; goto err; } + if (urb->status) { + DBG(GENERAL, "nonzero read bulk status received: %d\n", urb->status); + XUSB_COUNTER(xusb, RX_ERRORS)++; + goto err; + } size = urb->actual_length; if(size == 0) { static int rate_limit; @@ -928,10 +948,10 @@ static void xpp_receive_callback(USB_PASS_CB(urb)) goto err; } atomic_set(&xframe->frame_len, size); - do_gettimeofday(&xframe->tv_received); + xframe->tv_received = now; // if (print_dbg) -// dump_xframe("USB_FRAME_RECEIVE", xbus, xframe); +// dump_xframe("USB_FRAME_RECEIVE", xbus, xframe, print_dbg); XUSB_COUNTER(xusb, RX_FRAMES)++; /* Send UP */ xbus_receive_xframe(xbus, xframe); @@ -963,7 +983,7 @@ int __init xpp_usb_init(void) int ret; //xusb_t *xusb; - INFO("revision %s [sizeof(uframe)=%d]\n", XPP_VERSION, sizeof(struct uframe)); + INFO("revision %s\n", XPP_VERSION); xusb_cache = kmem_cache_create("xusb_cache", sizeof(xframe_t) + XFRAME_DATASIZE, 0, 0, @@ -1033,6 +1053,7 @@ static int xusb_read_proc(char *page, char **start, off_t off, int count, int *e xusb->endpoints[XUSB_SEND].max_size ); len += sprintf(page + len, "\npending_writes=%d\n", atomic_read(&xusb->pending_writes)); + len += sprintf(page + len, "pending_reads=%d\n", atomic_read(&xusb->pending_reads)); len += sprintf(page + len, "max_tx_delay=%d\n", xusb->max_tx_delay); xusb->max_tx_delay = 0; #ifdef DEBUG_PCM_TIMING |