aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2006-01-13 04:52:38 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-31 20:23:40 -0500
commit6f7494759870ec6fbb066f7202c5585fe36fbe82 (patch)
tree1fcff14ece062fefba2712b55ab4bddd05866425 /drivers/usb
parent227d77611b31df5d9afa572b984f73640f54d490 (diff)
[PATCH] USBATM: measure buffer size in bytes; force valid sizes
Change the module parameters rcv_buf_size and snd_buf_size to specify buffer sizes in bytes rather than ATM cells. Since there is some danger that users may not notice this change, the parameters are renamed to rcv_buf_bytes etc. The transmit buffer needs to be a multiple of the ATM cell size in length, while the receive buffer should be a multiple of the endpoint maxpacket size (this wasn't enforced before, which causes trouble with isochronous transfers), so enforce these restrictions. Now that the usbatm probe method inspects the endpoint maxpacket size, minidriver bind routines need to set the correct alternate setting for the interface in their bind routine. This is the reason for the speedtch changes. Signed-off-by: Duncan Sands <baldrick@free.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/atm/speedtch.c30
-rw-r--r--drivers/usb/atm/usbatm.c90
2 files changed, 84 insertions, 36 deletions
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 43ec758b92b5..0e981672f149 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -89,6 +89,7 @@ MODULE_PARM_DESC(sw_buffering,
89 "Enable software buffering (default: " 89 "Enable software buffering (default: "
90 __MODULE_STRING(DEFAULT_SW_BUFFERING) ")"); 90 __MODULE_STRING(DEFAULT_SW_BUFFERING) ")");
91 91
92#define INTERFACE_DATA 1
92#define ENDPOINT_INT 0x81 93#define ENDPOINT_INT 0x81
93#define ENDPOINT_DATA 0x07 94#define ENDPOINT_DATA 0x07
94#define ENDPOINT_FIRMWARE 0x05 95#define ENDPOINT_FIRMWARE 0x05
@@ -98,6 +99,8 @@ MODULE_PARM_DESC(sw_buffering,
98struct speedtch_instance_data { 99struct speedtch_instance_data {
99 struct usbatm_data *usbatm; 100 struct usbatm_data *usbatm;
100 101
102 unsigned int altsetting;
103
101 struct work_struct status_checker; 104 struct work_struct status_checker;
102 105
103 unsigned char last_status; 106 unsigned char last_status;
@@ -270,6 +273,11 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
270 because we're in our own kernel thread anyway. */ 273 because we're in our own kernel thread anyway. */
271 msleep_interruptible(1000); 274 msleep_interruptible(1000);
272 275
276 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
277 usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->altsetting, ret);
278 goto out_free;
279 }
280
273 /* Enable software buffering, if requested */ 281 /* Enable software buffering, if requested */
274 if (sw_buffering) 282 if (sw_buffering)
275 speedtch_set_swbuff(instance, 1); 283 speedtch_set_swbuff(instance, 1);
@@ -586,11 +594,6 @@ static int speedtch_atm_start(struct usbatm_data *usbatm, struct atm_dev *atm_de
586 594
587 atm_dbg(usbatm, "%s entered\n", __func__); 595 atm_dbg(usbatm, "%s entered\n", __func__);
588 596
589 if ((ret = usb_set_interface(usb_dev, 1, altsetting)) < 0) {
590 atm_dbg(usbatm, "%s: usb_set_interface returned %d!\n", __func__, ret);
591 return ret;
592 }
593
594 /* Set MAC address, it is stored in the serial number */ 597 /* Set MAC address, it is stored in the serial number */
595 memset(atm_dev->esi, 0, sizeof(atm_dev->esi)); 598 memset(atm_dev->esi, 0, sizeof(atm_dev->esi));
596 if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) { 599 if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) {
@@ -725,6 +728,23 @@ static int speedtch_bind(struct usbatm_data *usbatm,
725 728
726 instance->usbatm = usbatm; 729 instance->usbatm = usbatm;
727 730
731 /* altsetting may change at any moment, so take a snapshot */
732 instance->altsetting = altsetting;
733
734 if (instance->altsetting)
735 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
736 usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->altsetting, ret);
737 instance->altsetting = 0; /* fall back to default */
738 }
739
740 if (!instance->altsetting) {
741 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ALTSETTING)) < 0) {
742 usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ALTSETTING, ret);
743 goto fail_free;
744 }
745 instance->altsetting = DEFAULT_ALTSETTING;
746 }
747
728 INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance); 748 INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance);
729 749
730 instance->status_checker.timer.function = speedtch_status_poll; 750 instance->status_checker.timer.function = speedtch_status_poll;
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
113static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS; 112static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS;
114static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS; 113static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS;
115static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE; 114static unsigned int rcv_buf_bytes = UDSL_DEFAULT_RCV_BUF_SIZE;
116static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE; 115static unsigned int snd_buf_bytes = UDSL_DEFAULT_SND_BUF_SIZE;
117 116
118module_param(num_rcv_urbs, uint, S_IRUGO); 117module_param(num_rcv_urbs, uint, S_IRUGO);
119MODULE_PARM_DESC(num_rcv_urbs, 118MODULE_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
130module_param(rcv_buf_size, uint, S_IRUGO); 129module_param(rcv_buf_bytes, uint, S_IRUGO);
131MODULE_PARM_DESC(rcv_buf_size, 130MODULE_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
136module_param(snd_buf_size, uint, S_IRUGO); 135module_param(snd_buf_bytes, uint, S_IRUGO);
137MODULE_PARM_DESC(snd_buf_size, 136MODULE_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;