summaryrefslogtreecommitdiff
path: root/xpp/xpp_usb.c
diff options
context:
space:
mode:
authortzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-07-06 13:47:05 +0000
committertzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-07-06 13:47:05 +0000
commit39a1812c1ef76b6a792f00087f1e507616bbbb25 (patch)
treee50633c999779c514ef16f4a2ce7a70fc7511c9e /xpp/xpp_usb.c
parent70ef1183eba2d2fe4f00668fd3438b7f1c842c94 (diff)
Tons of updates to the Astribank (xpp) driver:
* xpd_fxo.ko (FXO span) is now operational * Remove obsolete .inc initialization files (we use user-space init) * Added an install target to the utils dir. * Updated README.Astribank accordingly. * Using RBS signalling, as caller ID did not work well otherwise. * Better handling of USB protocol errors. * Fixed some procfs-related races. * per-card-module ioctls. * fxotune support. * opermode support (set through /etc/default/zaptel for now) * Userspace initialization script can also read registers. * Power calibration works (and implemented in perl) * some fine-tuning to the regster initialization parameters. * Leds turn on before registration and turn off after it. git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1204 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'xpp/xpp_usb.c')
-rw-r--r--xpp/xpp_usb.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/xpp/xpp_usb.c b/xpp/xpp_usb.c
index 4b67299..4f81680 100644
--- a/xpp/xpp_usb.c
+++ b/xpp/xpp_usb.c
@@ -115,6 +115,8 @@ static struct xusb_counters {
#define XUSB_COUNTER_MAX ARRAY_SIZE(xusb_counters)
+#define MAX_PENDING_WRITES 100
+
enum xusb_dir {
XUSB_RECV = 0,
XUSB_SEND = 1,
@@ -138,6 +140,7 @@ typedef struct xpp_usb_bus {
int present; /* if the device is not disconnected */
int reading; /* is the read_urb reading (listening) */
+ atomic_t pending_writes; /* submited but not out yet */
struct semaphore sem; /* locks this structure */
int counters[XUSB_COUNTER_MAX];
} xusb_t;
@@ -311,6 +314,14 @@ static int xusb_packet_send(xbus_t *xbus, xpacket_t *pack)
ret = -EBADF;
goto out;
}
+ atomic_inc(&xusb->pending_writes);
+ if(atomic_read(&xusb->pending_writes) > MAX_PENDING_WRITES) {
+ static int rate_limit;
+
+ if((rate_limit++ % 1000) < 10)
+ ERR("%s: %s: more than %d pending writes. Dropping.\n", __FUNCTION__, xbus->busname, MAX_PENDING_WRITES);
+ ret = -ENODEV;
+ }
if(pack->content.opcode == XPROTO_NAME(GLOBAL,PCM_WRITE))
XUSB_COUNTER(xusb, PCM_WRITES)++;
out:
@@ -395,14 +406,8 @@ static const struct xusb_model_info {
/* table of devices that work with this driver */
static const struct usb_device_id xusb_table [] = {
// { USB_DEVICE(0x04B4, 0x8613) }, // default of cypress
- { USB_DEVICE(0x0547, 0x1002), .driver_info=(kernel_ulong_t)&model_table[0] }, // bulkloop.hex
-// { USB_DEVICE(0x04B4, 0x1004), .driver_info=(kernel_ulong_t)&model_table[1] }, // FPGA_bulkloop.hex
-// { USB_DEVICE(0x04B4, 0x1004), .driver_info=(kernel_ulong_t)&model_table[2] }, // FIXME: temporary test for Dima
{ USB_DEVICE(0xE4E4, 0x2211), .driver_info=(kernel_ulong_t)&model_table[2] }, // FPGA_XPD.hex
{ USB_DEVICE(0xE4E4, 0x1132), .driver_info=(kernel_ulong_t)&model_table[2] }, // FPGA_XPD.hex
-// { USB_DEVICE(0x04B4, 0x1004), .driver_info=(kernel_ulong_t)&model_table[2] }, // TEST ONLY
- //{ USB_DEVICE(0x0548, 0x1) },
- //{ USB_DEVICE(0x062a, 0x0) },
/* "Gadget Zero" firmware runs under Linux */
//{ USB_DEVICE(0x0525, 0xa4a0) },
{ } /* Terminating entry */
@@ -556,6 +561,7 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i
memset(xusb, 0, sizeof(xusb_t));
init_MUTEX (&xusb->sem);
+ atomic_set(&xusb->pending_writes, 0);
xusb->udev = udev;
xusb->interface = interface;
xusb->model_info = model_info;
@@ -631,6 +637,7 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i
retval = -EIO;
goto probe_failed;
}
+ procsummary->owner = THIS_MODULE;
#endif
bus_count++;
retval = usb_submit_urb(xusb->read_urb, GFP_ATOMIC);
@@ -732,6 +739,7 @@ static void xpp_send_callback(struct urb *urb, struct pt_regs *regs)
xbus_t *xbus = xusb->xbus;
BUG_ON(!xbus);
+ atomic_dec(&xusb->pending_writes);
/* sync/async unlink faults aren't errors */
if (urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET)) {
static int rate_limit;
@@ -739,11 +747,11 @@ static void xpp_send_callback(struct urb *urb, struct pt_regs *regs)
DBG("nonzero read bulk status received: %d\n", urb->status);
XUSB_COUNTER(xusb, TX_ERRORS)++;
}
+ xpp_urb_delete(urb);
if(!xusb->present) {
ERR("A packet from non-connected device?\n");
return;
}
- xpp_urb_delete(urb);
/* allow device read, write and ioctl */
XUSB_COUNTER(xusb, TX_PACKETS)++;
}
@@ -875,6 +883,7 @@ static int xusb_read_proc(char *page, char **start, off_t off, int count, int *e
xusb->endpoints[XUSB_SEND].ep_addr,
xusb->endpoints[XUSB_SEND].max_size
);
+ len += sprintf(page + len, "\npending_writes=%d\n", atomic_read(&xusb->pending_writes));
#ifdef DEBUG_PCM_TIMING
len += sprintf(page + len, "\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n", stamp_last_pcm_read, accumulate_diff);
#endif