From 1a571d19740d87e24b92ef49a2d38b26256112ae Mon Sep 17 00:00:00 2001 From: tzafrir Date: Fri, 7 Mar 2008 00:45:53 +0000 Subject: xpp.r5512: * Build: - Zaptel >= 1.4.9 is migrating to storing kernel stuff in zaptel/kernel/* - We conditionally use old/new directory scheme: In xpp/Kbuild and xpp/utils/Makefile use ZAP_KERNEL variable, so it's not confused with ZAPTEL_DIR (which appears in zaptel/Makefile as well). - Fix compile warnings on 64 bit systems. - Compile fixes for kernel-2.6.24 * UDEV: - /etc/udev/rules.d/xpp.rules now uses XPP_INIT_DIR to find astribank_hook. - astribank_hook: Modify to do nothing. Add some documentation. * Autoconfiguration -- zapconf: - Don't fail zapconf et.al. if no config file was found. - Skip the 'IRQ Missing:' line in /proc/zaptel/nnn for wcte1xp(?). - Add some newer Digium cards to our hardware inventory. - Partially handle cases where the /proc/zaptel strings does not contain info about E1/T1/J1 or NT/TE. * Better SYNC: - Finer tuning of PLL (New firmware). - Change calculation algorithm of sync offset. It now copes better with the variance in USB frame reception timing. - Statistics: . The view of results was moved from /proc/xpp/XBUS-*/summary to a new /sys/bus/astribanks/devices/xbus-*/timing and enhanced. . A new xpp_timing script shows all astribanks. . A new write only /sys/bus/astribanks/devices/xbus-*/cls is used to clear statistics. Eventually, clearing of XBUS related statistics should be done here. One that was migrated is the clearing of 'PCM [TR]X:' numbers currently appearing in /proc/xpp/XBUS-*/summary (they should be moved too later). - Shorten the strings representation sync_mode ("SYNC_MODE_AB" -> "AB") adapted their use in printk and /proc so the text is clear. - Added a command line parameter xpp.disable_pll_sync to stop all adjustments command to AB (calculations still continue as usual). * PRI: - 4 port support - set clocking master span via ztcfg, like other zaptel devices. * FXO: - Fix false hangups in some countries (voltage fluctuations). - Some countries send caller-id before first ring. Added code to handle caller-id PCM pass through according to a new command line parameter (xpd_fxo.caller_id_style). - No longer sends an event on zt_open. See #12160 . * Misc: - Adapt to zaptel-1.4.8 and above ztscan: added fields returend by new ZT_SPANSTAT_V2 ioctl() - Document sysfs and waitfor_xpds. - Miscelaneous optimizations and bugfixes. - Remove deprecated pcm_tasklet parameter. The rx_tasklet parameter has replaced it a long time ago. - Add RX_CMD counter to /proc/xpp/XBUS-*/summary - Unclutter some of the usb disconnect messages. - xpp_usb: minor preformance improvements in receive. Expose the number of pending receive URB's in /proc/xpp/XBUS-*/xpp_usb Merged revisions 3952 via svnmerge from http://svn.digium.com/svn/zaptel/branches/1.2 git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@3957 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- kernel/xpp/xpp_usb.c | 93 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 36 deletions(-) (limited to 'kernel/xpp/xpp_usb.c') diff --git a/kernel/xpp/xpp_usb.c b/kernel/xpp/xpp_usb.c index 785e713..796b127 100644 --- a/kernel/xpp/xpp_usb.c +++ b/kernel/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 -- cgit v1.2.3