summaryrefslogtreecommitdiff
path: root/kernel/xpp/xpp_usb.c
diff options
context:
space:
mode:
authortzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-03-07 00:45:53 +0000
committertzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-03-07 00:45:53 +0000
commit1a571d19740d87e24b92ef49a2d38b26256112ae (patch)
tree8490182ea096b25f977d73c8c7a89b286014b94c /kernel/xpp/xpp_usb.c
parent92d02c5fadec34a75c085e9f95eeab268c3683c8 (diff)
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
Diffstat (limited to 'kernel/xpp/xpp_usb.c')
-rw-r--r--kernel/xpp/xpp_usb.c93
1 files changed, 57 insertions, 36 deletions
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