diff options
Diffstat (limited to 'drivers/usb/atm/usbatm.c')
-rw-r--r-- | drivers/usb/atm/usbatm.c | 90 |
1 files changed, 59 insertions, 31 deletions
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 98b74b9dcdd2..1d829c29c86d 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c | |||
@@ -99,12 +99,11 @@ static const char usbatm_driver_name[] = "usbatm"; | |||
99 | 99 | ||
100 | #define UDSL_MAX_RCV_URBS 16 | 100 | #define UDSL_MAX_RCV_URBS 16 |
101 | #define UDSL_MAX_SND_URBS 16 | 101 | #define UDSL_MAX_SND_URBS 16 |
102 | #define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */ | 102 | #define UDSL_MAX_BUF_SIZE 64 * 1024 /* bytes */ |
103 | #define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */ | ||
104 | #define UDSL_DEFAULT_RCV_URBS 4 | 103 | #define UDSL_DEFAULT_RCV_URBS 4 |
105 | #define UDSL_DEFAULT_SND_URBS 4 | 104 | #define UDSL_DEFAULT_SND_URBS 4 |
106 | #define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */ | 105 | #define UDSL_DEFAULT_RCV_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */ |
107 | #define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */ | 106 | #define UDSL_DEFAULT_SND_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */ |
108 | 107 | ||
109 | #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) | 108 | #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) |
110 | 109 | ||
@@ -112,8 +111,8 @@ static const char usbatm_driver_name[] = "usbatm"; | |||
112 | 111 | ||
113 | static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS; | 112 | static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS; |
114 | static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS; | 113 | static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS; |
115 | static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE; | 114 | static unsigned int rcv_buf_bytes = UDSL_DEFAULT_RCV_BUF_SIZE; |
116 | static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE; | 115 | static unsigned int snd_buf_bytes = UDSL_DEFAULT_SND_BUF_SIZE; |
117 | 116 | ||
118 | module_param(num_rcv_urbs, uint, S_IRUGO); | 117 | module_param(num_rcv_urbs, uint, S_IRUGO); |
119 | MODULE_PARM_DESC(num_rcv_urbs, | 118 | MODULE_PARM_DESC(num_rcv_urbs, |
@@ -127,15 +126,15 @@ MODULE_PARM_DESC(num_snd_urbs, | |||
127 | __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: " | 126 | __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: " |
128 | __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")"); | 127 | __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")"); |
129 | 128 | ||
130 | module_param(rcv_buf_size, uint, S_IRUGO); | 129 | module_param(rcv_buf_bytes, uint, S_IRUGO); |
131 | MODULE_PARM_DESC(rcv_buf_size, | 130 | MODULE_PARM_DESC(rcv_buf_bytes, |
132 | "Size of the buffers used for reception in ATM cells (range: 1-" | 131 | "Size of the buffers used for reception, in bytes (range: 1-" |
133 | __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: " | 132 | __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: " |
134 | __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")"); | 133 | __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")"); |
135 | 134 | ||
136 | module_param(snd_buf_size, uint, S_IRUGO); | 135 | module_param(snd_buf_bytes, uint, S_IRUGO); |
137 | MODULE_PARM_DESC(snd_buf_size, | 136 | MODULE_PARM_DESC(snd_buf_bytes, |
138 | "Size of the buffers used for transmission in ATM cells (range: 1-" | 137 | "Size of the buffers used for transmission, in bytes (range: 1-" |
139 | __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: " | 138 | __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: " |
140 | __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")"); | 139 | __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")"); |
141 | 140 | ||
@@ -430,14 +429,14 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, | |||
430 | { | 429 | { |
431 | struct usbatm_control *ctrl = UDSL_SKB(skb); | 430 | struct usbatm_control *ctrl = UDSL_SKB(skb); |
432 | struct atm_vcc *vcc = ctrl->atm.vcc; | 431 | struct atm_vcc *vcc = ctrl->atm.vcc; |
433 | unsigned int num_written; | 432 | unsigned int bytes_written; |
434 | unsigned int stride = instance->tx_channel.stride; | 433 | unsigned int stride = instance->tx_channel.stride; |
435 | 434 | ||
436 | vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space); | 435 | vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space); |
437 | UDSL_ASSERT(!(avail_space % stride)); | 436 | UDSL_ASSERT(!(avail_space % stride)); |
438 | 437 | ||
439 | for (num_written = 0; num_written < avail_space && ctrl->len; | 438 | for (bytes_written = 0; bytes_written < avail_space && ctrl->len; |
440 | num_written += stride, target += stride) { | 439 | bytes_written += stride, target += stride) { |
441 | unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD); | 440 | unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD); |
442 | unsigned int left = ATM_CELL_PAYLOAD - data_len; | 441 | unsigned int left = ATM_CELL_PAYLOAD - data_len; |
443 | u8 *ptr = target; | 442 | u8 *ptr = target; |
@@ -480,7 +479,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, | |||
480 | ctrl->crc = crc32_be(ctrl->crc, ptr, left); | 479 | ctrl->crc = crc32_be(ctrl->crc, ptr, left); |
481 | } | 480 | } |
482 | 481 | ||
483 | return num_written; | 482 | return bytes_written; |
484 | } | 483 | } |
485 | 484 | ||
486 | 485 | ||
@@ -524,7 +523,7 @@ static void usbatm_tx_process(unsigned long data) | |||
524 | struct sk_buff *skb = instance->current_skb; | 523 | struct sk_buff *skb = instance->current_skb; |
525 | struct urb *urb = NULL; | 524 | struct urb *urb = NULL; |
526 | const unsigned int buf_size = instance->tx_channel.buf_size; | 525 | const unsigned int buf_size = instance->tx_channel.buf_size; |
527 | unsigned int num_written = 0; | 526 | unsigned int bytes_written = 0; |
528 | u8 *buffer = NULL; | 527 | u8 *buffer = NULL; |
529 | 528 | ||
530 | if (!skb) | 529 | if (!skb) |
@@ -536,16 +535,16 @@ static void usbatm_tx_process(unsigned long data) | |||
536 | if (!urb) | 535 | if (!urb) |
537 | break; /* no more senders */ | 536 | break; /* no more senders */ |
538 | buffer = urb->transfer_buffer; | 537 | buffer = urb->transfer_buffer; |
539 | num_written = (urb->status == -EAGAIN) ? | 538 | bytes_written = (urb->status == -EAGAIN) ? |
540 | urb->transfer_buffer_length : 0; | 539 | urb->transfer_buffer_length : 0; |
541 | } | 540 | } |
542 | 541 | ||
543 | num_written += usbatm_write_cells(instance, skb, | 542 | bytes_written += usbatm_write_cells(instance, skb, |
544 | buffer + num_written, | 543 | buffer + bytes_written, |
545 | buf_size - num_written); | 544 | buf_size - bytes_written); |
546 | 545 | ||
547 | vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p", | 546 | vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p", |
548 | __func__, num_written, skb, urb); | 547 | __func__, bytes_written, skb, urb); |
549 | 548 | ||
550 | if (!UDSL_SKB(skb)->len) { | 549 | if (!UDSL_SKB(skb)->len) { |
551 | struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc; | 550 | struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc; |
@@ -556,8 +555,8 @@ static void usbatm_tx_process(unsigned long data) | |||
556 | skb = skb_dequeue(&instance->sndqueue); | 555 | skb = skb_dequeue(&instance->sndqueue); |
557 | } | 556 | } |
558 | 557 | ||
559 | if (num_written == buf_size || (!skb && num_written)) { | 558 | if (bytes_written == buf_size || (!skb && bytes_written)) { |
560 | urb->transfer_buffer_length = num_written; | 559 | urb->transfer_buffer_length = bytes_written; |
561 | 560 | ||
562 | if (usbatm_submit_urb(urb)) | 561 | if (usbatm_submit_urb(urb)) |
563 | break; | 562 | break; |
@@ -990,6 +989,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, | |||
990 | char *buf; | 989 | char *buf; |
991 | int error = -ENOMEM; | 990 | int error = -ENOMEM; |
992 | int i, length; | 991 | int i, length; |
992 | unsigned int maxpacket, num_packets; | ||
993 | 993 | ||
994 | dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n", | 994 | dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n", |
995 | __func__, driver->driver_name, | 995 | __func__, driver->driver_name, |
@@ -1058,10 +1058,38 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, | |||
1058 | instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->out); | 1058 | instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->out); |
1059 | instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding; | 1059 | instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding; |
1060 | instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding; | 1060 | instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding; |
1061 | instance->rx_channel.buf_size = rcv_buf_size * instance->rx_channel.stride; | ||
1062 | instance->tx_channel.buf_size = snd_buf_size * instance->tx_channel.stride; | ||
1063 | instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance; | 1061 | instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance; |
1064 | 1062 | ||
1063 | /* tx buffer size must be a positive multiple of the stride */ | ||
1064 | instance->tx_channel.buf_size = max (instance->tx_channel.stride, | ||
1065 | snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride)); | ||
1066 | |||
1067 | /* rx buffer size must be a positive multiple of the endpoint maxpacket */ | ||
1068 | maxpacket = usb_maxpacket(usb_dev, instance->rx_channel.endpoint, 0); | ||
1069 | |||
1070 | if ((maxpacket < 1) || (maxpacket > UDSL_MAX_BUF_SIZE)) { | ||
1071 | dev_err(dev, "%s: invalid endpoint %02x!\n", __func__, | ||
1072 | usb_pipeendpoint(instance->rx_channel.endpoint)); | ||
1073 | error = -EINVAL; | ||
1074 | goto fail_unbind; | ||
1075 | } | ||
1076 | |||
1077 | num_packets = max (1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */ | ||
1078 | |||
1079 | if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE) | ||
1080 | num_packets--; | ||
1081 | |||
1082 | instance->rx_channel.buf_size = num_packets * maxpacket; | ||
1083 | |||
1084 | #ifdef DEBUG | ||
1085 | for (i = 0; i < 2; i++) { | ||
1086 | struct usbatm_channel *channel = i ? | ||
1087 | &instance->tx_channel : &instance->rx_channel; | ||
1088 | |||
1089 | dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", __func__, channel->buf_size, i ? "tx" : "rx", channel); | ||
1090 | } | ||
1091 | #endif | ||
1092 | |||
1065 | skb_queue_head_init(&instance->sndqueue); | 1093 | skb_queue_head_init(&instance->sndqueue); |
1066 | 1094 | ||
1067 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { | 1095 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { |
@@ -1232,10 +1260,10 @@ static int __init usbatm_usb_init(void) | |||
1232 | 1260 | ||
1233 | if ((num_rcv_urbs > UDSL_MAX_RCV_URBS) | 1261 | if ((num_rcv_urbs > UDSL_MAX_RCV_URBS) |
1234 | || (num_snd_urbs > UDSL_MAX_SND_URBS) | 1262 | || (num_snd_urbs > UDSL_MAX_SND_URBS) |
1235 | || (rcv_buf_size < 1) | 1263 | || (rcv_buf_bytes < 1) |
1236 | || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE) | 1264 | || (rcv_buf_bytes > UDSL_MAX_BUF_SIZE) |
1237 | || (snd_buf_size < 1) | 1265 | || (snd_buf_bytes < 1) |
1238 | || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE)) | 1266 | || (snd_buf_bytes > UDSL_MAX_BUF_SIZE)) |
1239 | return -EINVAL; | 1267 | return -EINVAL; |
1240 | 1268 | ||
1241 | return 0; | 1269 | return 0; |