diff options
Diffstat (limited to 'xpp/xpp_usb.c')
-rw-r--r-- | xpp/xpp_usb.c | 23 |
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 |