RFC : usbatm and iso
matthieu castet
castet.matthieu at free.fr
Mon Feb 7 10:36:58 EST 2005
Hi,
I attached a patch for adding iso to the new library.
Seem to work well but need more testing.
cheers,
Matthieu
-------------- next part --------------
Index: usbatm.c
===================================================================
RCS file: /home/cvs/usbatm/usbatm.c,v
retrieving revision 1.4
diff -u -r1.4 usbatm.c
--- usbatm.c 1 Feb 2005 23:20:49 -0000 1.4
+++ usbatm.c 7 Feb 2005 15:32:37 -0000
@@ -145,6 +145,7 @@
static unsigned int num_snd_bufs = UDSL_DEFAULT_SND_BUFS;
static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE;
static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE;
+static unsigned int rcv_buf_per_urb = UDSL_DEFAULT_RCV_BUF_PER_URB;
module_param(num_rcv_urbs, uint, 0444);
MODULE_PARM_DESC(num_rcv_urbs,
@@ -182,6 +183,12 @@
__MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
__MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
+module_param(rcv_buf_per_urb, uint, 0444);
+MODULE_PARM_DESC(rcv_buf_per_urb,
+ "Number of the buffer in iso urb used for reception (range: 0-"
+ __MODULE_STRING(UDSL_MAX_RCV_BUF_PER_URB) ", default: "
+ __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_PER_URB) ")");
+
/* ATM */
static void usbatm_atm_dev_close(struct atm_dev *dev);
@@ -456,6 +463,38 @@
/**************
** receive **
**************/
+static inline void usbatm_usb_fill_iso_urb (struct urb *urb,
+ struct usb_device *dev,
+ unsigned int pipe,
+ void *transfer_buffer,
+ int buffer_length,
+ int frame_size,
+ usb_complete_t complete,
+ void *context)
+{
+ int j;
+
+ //spin_lock_init(&urb->lock);
+ urb->dev = dev;
+ urb->pipe = pipe;
+ urb->transfer_buffer = transfer_buffer;
+ urb->transfer_buffer_length = buffer_length;
+ urb->complete = complete;
+ urb->context = context;
+
+ urb->interval = 1;
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->number_of_packets = rcv_buf_per_urb;
+
+ for (j = 0; j < urb->number_of_packets; j++) {
+ urb->iso_frame_desc[j].offset = j * frame_size;
+ urb->iso_frame_desc[j].length = frame_size;
+
+ urb->iso_frame_desc[j].status = 0;
+ urb->iso_frame_desc[j].actual_length = 0;
+ }
+ urb->status = 0;
+}
static void usbatm_complete_receive(struct urb *urb, struct pt_regs *regs)
{
@@ -472,17 +511,44 @@
instance = rcv->instance;
buf = rcv->buffer;
- buf->filled_cells = urb->actual_length / (ATM_CELL_SIZE + instance->rx_padding);
+ if ( urb->actual_length <= 0 && !urb->status) {
+ int err;
+ if ((err = usb_submit_urb(rcv->urb, GFP_ATOMIC)) < 0) {
+ dbg("usbatm_complete_receive: urb submission failed (%d)!", err);
+ list_add(&buf->list, &instance->spare_receive_buffers);
+ spin_lock_irq(&instance->receive_lock);
+ list_add(&rcv->list, &instance->spare_receivers);
+ spin_unlock_irq(&instance->receive_lock);
+ tasklet_schedule(&instance->receive_tasklet);
+ }
+ return;
+ }
+
+ if (usb_pipeisoc(instance->rx_endpoint)) {
+ int i;
+ for (i = 0; i < urb->number_of_packets; i++) {
+ buf->frames[i].status = urb->iso_frame_desc[i].status;
+ buf->frames[i].filled_cells = urb->iso_frame_desc[i].actual_length / (ATM_CELL_SIZE + instance->rx_padding);
+ UDSL_ASSERT(buf->frames[i].filled_cells <= instance->iso_frame_size);
+ vdbg("usbatm_complete_receive: urb 0x%p, frame %d, status %d, actual_length %d ,filled_cells %d", urb, i, buf->frames[i].status, urb->iso_frame_desc[i].actual_length, buf->frames[i].filled_cells);
+ }
+ }
+ else {
+ buf->filled_cells = urb->actual_length / (ATM_CELL_SIZE + instance->rx_padding);
+ }
vdbg("usbatm_complete_receive: urb 0x%p, status %d, actual_length %d, filled_cells %u, rcv 0x%p, buf 0x%p", urb, urb->status, urb->actual_length, buf->filled_cells, rcv, buf);
- UDSL_ASSERT(buf->filled_cells <= rcv_buf_size);
+ UDSL_ASSERT(!usb_pipeisoc(instance->rx_endpoint)
+ && buf->filled_cells <= rcv_buf_size);
/* may not be in_interrupt() */
spin_lock_irqsave(&instance->receive_lock, flags);
list_add(&rcv->list, &instance->spare_receivers);
list_add_tail(&buf->list, &instance->filled_receive_buffers);
- if (likely(!urb->status))
+ if (likely(!urb->status) ||
+ /* via chipset produce lot's of crc error...*/
+ (usb_pipeisoc(instance->rx_endpoint) && urb->status == -EILSEQ))
tasklet_schedule(&instance->receive_tasklet);
spin_unlock_irqrestore(&instance->receive_lock, flags);
}
@@ -512,11 +578,21 @@
rcv->buffer = buf;
- usb_fill_bulk_urb(rcv->urb, instance->usb_dev,
- instance->rx_endpoint,
- buf->base,
- rcv_buf_size * (ATM_CELL_SIZE + instance->rx_padding),
- usbatm_complete_receive, rcv);
+ /* refill the urb because the buf could have changed...*/
+ /* urb->transfer_buffer and urb->context should be enought */
+ if (usb_pipeisoc(instance->rx_endpoint))
+ usbatm_usb_fill_iso_urb(rcv->urb, instance->usb_dev,
+ instance->rx_endpoint,
+ buf->base,
+ instance->iso_frame_size * rcv_buf_per_urb,
+ instance->iso_frame_size,
+ usbatm_complete_receive, rcv);
+ else
+ usb_fill_bulk_urb(rcv->urb, instance->usb_dev,
+ instance->rx_endpoint,
+ buf->base,
+ rcv_buf_size * (ATM_CELL_SIZE + instance->rx_padding),
+ usbatm_complete_receive, rcv);
vdbg("usbatm_process_receive: sending urb 0x%p, rcv 0x%p, buf 0x%p",
rcv->urb, rcv, buf);
@@ -542,7 +618,17 @@
spin_unlock_irq(&instance->receive_lock);
vdbg("usbatm_process_receive: processing buf 0x%p", buf);
- usbatm_extract_cells(instance, buf->base, buf->filled_cells);
+ if (usb_pipeisoc(instance->rx_endpoint)) {
+ int i;
+ for (i=0 ; i < rcv_buf_per_urb; i++) {
+ if (buf->frames[i].status == 0) {
+ usbatm_extract_cells(instance, buf->base + i * instance->iso_frame_size, buf->frames[i].filled_cells);
+ }
+ }
+ }
+ else
+ usbatm_extract_cells(instance, buf->base, buf->filled_cells);
+
list_add(&buf->list, &instance->spare_receive_buffers);
goto made_progress;
}
@@ -1037,6 +1123,8 @@
int error = -ENOMEM;
int ifnum = intf->altsetting->desc.bInterfaceNumber;
int i, length;
+ int nb_frames = 0;
+ int urb_size;
int need_heavy;
dev_dbg(&intf->dev, "trying device with vendor=0x%x, product=0x%x, ifnum %d\n", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
@@ -1062,9 +1150,18 @@
instance->usb_dev = dev;
instance->usb_intf = intf;
instance->tx_endpoint = usb_sndbulkpipe(dev, driver->out);
- instance->rx_endpoint = usb_rcvbulkpipe(dev, driver->in);
+ if (driver->iso_frame_size) {
+ nb_frames = rcv_buf_per_urb;
+ urb_size = driver->iso_frame_size * rcv_buf_per_urb;
+ instance->rx_endpoint = usb_rcvisocpipe(dev, driver->in);
+ }
+ else {
+ urb_size = rcv_buf_size * (ATM_CELL_SIZE + instance->rx_padding);
+ instance->rx_endpoint = usb_rcvbulkpipe(dev, driver->in);
+ }
instance->tx_padding = driver->tx_padding;
instance->rx_padding = driver->rx_padding;
+ instance->iso_frame_size = driver->iso_frame_size;
INIT_LIST_HEAD(&instance->vcc_list);
@@ -1089,7 +1186,7 @@
for (i = 0; i < num_rcv_urbs; i++) {
struct usbatm_receiver *rcv = &(instance->receivers[i]);
- if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
+ if (!(rcv->urb = usb_alloc_urb(nb_frames, GFP_KERNEL))) {
dev_dbg(&intf->dev, "no memory for receive urb %d!\n", i);
goto fail;
}
@@ -1102,8 +1199,7 @@
for (i = 0; i < num_rcv_bufs; i++) {
struct usbatm_receive_buffer *buf = &(instance->receive_buffers[i]);
- buf->base = kmalloc(rcv_buf_size * (ATM_CELL_SIZE + instance->rx_padding),
- GFP_KERNEL);
+ buf->base = kmalloc(urb_size, GFP_KERNEL);
if (!buf->base) {
dev_dbg(&intf->dev, "no memory for receive buffer %d!\n", i);
goto fail;
@@ -1292,6 +1388,7 @@
|| (num_rcv_bufs > UDSL_MAX_RCV_BUFS)
|| (num_snd_bufs > UDSL_MAX_SND_BUFS)
|| (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE)
+ || (rcv_buf_per_urb > UDSL_MAX_RCV_BUF_PER_URB)
|| (snd_buf_size > UDSL_MAX_SND_BUF_SIZE))
return -EINVAL;
Index: usbatm.h
===================================================================
RCS file: /home/cvs/usbatm/usbatm.h,v
retrieving revision 1.8
diff -u -r1.8 usbatm.h
--- usbatm.h 1 Feb 2005 23:20:49 -0000 1.8
+++ usbatm.h 7 Feb 2005 15:32:37 -0000
@@ -88,6 +88,7 @@
unsigned rx_padding;
unsigned tx_padding;
+ unsigned iso_frame_size; /* if using iso urb, the size of a frame */
};
extern int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
@@ -103,19 +104,26 @@
#define UDSL_MAX_SND_BUFS 8
#define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */
#define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */
+#define UDSL_MAX_RCV_BUF_PER_URB 20
#define UDSL_DEFAULT_RCV_URBS 2
#define UDSL_DEFAULT_SND_URBS 2
#define UDSL_DEFAULT_RCV_BUFS 4
#define UDSL_DEFAULT_SND_BUFS 4
#define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */
#define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */
+#define UDSL_DEFAULT_RCV_BUF_PER_URB 16
/* receive */
+struct udsl_receive_iso_frame {
+ unsigned int filled_cells;
+ int status;
+};
struct usbatm_receive_buffer {
struct list_head list;
unsigned char *base;
+ struct udsl_receive_iso_frame frames[UDSL_MAX_RCV_BUF_PER_URB];
unsigned int filled_cells;
};
@@ -167,6 +175,7 @@
int rx_endpoint;
int tx_padding;
int rx_padding;
+ unsigned iso_frame_size;
/* ATM device part */
struct atm_dev *atm_dev;
More information about the Usbatm
mailing list