diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-06-26 01:31:38 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-06-26 01:31:38 -0400 |
commit | 4854c7b27f0975a2b629f35ea3996d2968eb7c4f (patch) | |
tree | 4102bdb70289764a2058aff0f907b13d7cf0e0d1 /drivers/usb | |
parent | 3cbd5b32cb625f5c0f1b1476d154fac873dd49ce (diff) | |
parent | fcc18e83e1f6fd9fa6b333735bf0fcd530655511 (diff) |
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/usb')
118 files changed, 3797 insertions, 4171 deletions
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 9b7d9769fdcc..c7123bf71c58 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -48,6 +48,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ | |||
48 | obj-$(CONFIG_USB_SERIAL) += serial/ | 48 | obj-$(CONFIG_USB_SERIAL) += serial/ |
49 | 49 | ||
50 | obj-$(CONFIG_USB_AUERSWALD) += misc/ | 50 | obj-$(CONFIG_USB_AUERSWALD) += misc/ |
51 | obj-$(CONFIG_USB_CY7C63) += misc/ | ||
51 | obj-$(CONFIG_USB_CYTHERM) += misc/ | 52 | obj-$(CONFIG_USB_CYTHERM) += misc/ |
52 | obj-$(CONFIG_USB_EMI26) += misc/ | 53 | obj-$(CONFIG_USB_EMI26) += misc/ |
53 | obj-$(CONFIG_USB_EMI62) += misc/ | 54 | obj-$(CONFIG_USB_EMI62) += misc/ |
@@ -61,6 +62,7 @@ obj-$(CONFIG_USB_TEST) += misc/ | |||
61 | obj-$(CONFIG_USB_USS720) += misc/ | 62 | obj-$(CONFIG_USB_USS720) += misc/ |
62 | obj-$(CONFIG_USB_PHIDGETSERVO) += misc/ | 63 | obj-$(CONFIG_USB_PHIDGETSERVO) += misc/ |
63 | obj-$(CONFIG_USB_SISUSBVGA) += misc/ | 64 | obj-$(CONFIG_USB_SISUSBVGA) += misc/ |
65 | obj-$(CONFIG_USB_APPLEDISPLAY) += misc/ | ||
64 | 66 | ||
65 | obj-$(CONFIG_USB_ATM) += atm/ | 67 | obj-$(CONFIG_USB_ATM) += atm/ |
66 | obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ | 68 | obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ |
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 546249843b8e..a38701c742c3 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c | |||
@@ -1039,7 +1039,7 @@ static void usbatm_tasklet_schedule(unsigned long data) | |||
1039 | tasklet_schedule((struct tasklet_struct *) data); | 1039 | tasklet_schedule((struct tasklet_struct *) data); |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | static inline void usbatm_init_channel(struct usbatm_channel *channel) | 1042 | static void usbatm_init_channel(struct usbatm_channel *channel) |
1043 | { | 1043 | { |
1044 | spin_lock_init(&channel->lock); | 1044 | spin_lock_init(&channel->lock); |
1045 | INIT_LIST_HEAD(&channel->list); | 1045 | INIT_LIST_HEAD(&channel->list); |
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c index 42d6823b82b3..70125c6d3be4 100644 --- a/drivers/usb/atm/xusbatm.c +++ b/drivers/usb/atm/xusbatm.c | |||
@@ -20,7 +20,6 @@ | |||
20 | ******************************************************************************/ | 20 | ******************************************************************************/ |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/netdevice.h> /* FIXME: required by linux/etherdevice.h */ | ||
24 | #include <linux/etherdevice.h> /* for random_ether_addr() */ | 23 | #include <linux/etherdevice.h> /* for random_ether_addr() */ |
25 | 24 | ||
26 | #include "usbatm.h" | 25 | #include "usbatm.h" |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 6dd339f4c0fc..d41dc67ba4cc 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -63,7 +63,7 @@ | |||
63 | #include <linux/mutex.h> | 63 | #include <linux/mutex.h> |
64 | #include <asm/uaccess.h> | 64 | #include <asm/uaccess.h> |
65 | #include <linux/usb.h> | 65 | #include <linux/usb.h> |
66 | #include <linux/usb_cdc.h> | 66 | #include <linux/usb/cdc.h> |
67 | #include <asm/byteorder.h> | 67 | #include <asm/byteorder.h> |
68 | #include <asm/unaligned.h> | 68 | #include <asm/unaligned.h> |
69 | #include <linux/list.h> | 69 | #include <linux/list.h> |
@@ -127,8 +127,8 @@ static int acm_wb_alloc(struct acm *acm) | |||
127 | wb->use = 1; | 127 | wb->use = 1; |
128 | return wbn; | 128 | return wbn; |
129 | } | 129 | } |
130 | wbn = (wbn + 1) % ACM_NWB; | 130 | wbn = (wbn + 1) % ACM_NW; |
131 | if (++i >= ACM_NWB) | 131 | if (++i >= ACM_NW) |
132 | return -1; | 132 | return -1; |
133 | } | 133 | } |
134 | } | 134 | } |
@@ -142,10 +142,9 @@ static int acm_wb_is_avail(struct acm *acm) | |||
142 | { | 142 | { |
143 | int i, n; | 143 | int i, n; |
144 | 144 | ||
145 | n = 0; | 145 | n = ACM_NW; |
146 | for (i = 0; i < ACM_NWB; i++) { | 146 | for (i = 0; i < ACM_NW; i++) { |
147 | if (!acm->wb[i].use) | 147 | n -= acm->wb[i].use; |
148 | n++; | ||
149 | } | 148 | } |
150 | return n; | 149 | return n; |
151 | } | 150 | } |
@@ -167,7 +166,7 @@ static void acm_write_done(struct acm *acm) | |||
167 | acm->write_ready = 1; | 166 | acm->write_ready = 1; |
168 | wbn = acm->write_current; | 167 | wbn = acm->write_current; |
169 | acm_wb_free(acm, wbn); | 168 | acm_wb_free(acm, wbn); |
170 | acm->write_current = (wbn + 1) % ACM_NWB; | 169 | acm->write_current = (wbn + 1) % ACM_NW; |
171 | spin_unlock_irqrestore(&acm->write_lock, flags); | 170 | spin_unlock_irqrestore(&acm->write_lock, flags); |
172 | } | 171 | } |
173 | 172 | ||
@@ -291,22 +290,32 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs) | |||
291 | struct acm_rb *buf; | 290 | struct acm_rb *buf; |
292 | struct acm_ru *rcv = urb->context; | 291 | struct acm_ru *rcv = urb->context; |
293 | struct acm *acm = rcv->instance; | 292 | struct acm *acm = rcv->instance; |
293 | int status = urb->status; | ||
294 | dbg("Entering acm_read_bulk with status %d\n", urb->status); | 294 | dbg("Entering acm_read_bulk with status %d\n", urb->status); |
295 | 295 | ||
296 | if (!ACM_READY(acm)) | 296 | if (!ACM_READY(acm)) |
297 | return; | 297 | return; |
298 | 298 | ||
299 | if (urb->status) | 299 | if (status) |
300 | dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status); | 300 | dev_dbg(&acm->data->dev, "bulk rx status %d\n", status); |
301 | 301 | ||
302 | buf = rcv->buffer; | 302 | buf = rcv->buffer; |
303 | buf->size = urb->actual_length; | 303 | buf->size = urb->actual_length; |
304 | 304 | ||
305 | spin_lock(&acm->read_lock); | 305 | if (likely(status == 0)) { |
306 | list_add_tail(&rcv->list, &acm->spare_read_urbs); | 306 | spin_lock(&acm->read_lock); |
307 | list_add_tail(&buf->list, &acm->filled_read_bufs); | 307 | list_add_tail(&rcv->list, &acm->spare_read_urbs); |
308 | spin_unlock(&acm->read_lock); | 308 | list_add_tail(&buf->list, &acm->filled_read_bufs); |
309 | 309 | spin_unlock(&acm->read_lock); | |
310 | } else { | ||
311 | /* we drop the buffer due to an error */ | ||
312 | spin_lock(&acm->read_lock); | ||
313 | list_add_tail(&rcv->list, &acm->spare_read_urbs); | ||
314 | list_add(&buf->list, &acm->spare_read_bufs); | ||
315 | spin_unlock(&acm->read_lock); | ||
316 | /* nevertheless the tasklet must be kicked unconditionally | ||
317 | so the queue cannot dry up */ | ||
318 | } | ||
310 | tasklet_schedule(&acm->urb_task); | 319 | tasklet_schedule(&acm->urb_task); |
311 | } | 320 | } |
312 | 321 | ||
@@ -464,10 +473,10 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
464 | INIT_LIST_HEAD(&acm->spare_read_urbs); | 473 | INIT_LIST_HEAD(&acm->spare_read_urbs); |
465 | INIT_LIST_HEAD(&acm->spare_read_bufs); | 474 | INIT_LIST_HEAD(&acm->spare_read_bufs); |
466 | INIT_LIST_HEAD(&acm->filled_read_bufs); | 475 | INIT_LIST_HEAD(&acm->filled_read_bufs); |
467 | for (i = 0; i < ACM_NRU; i++) { | 476 | for (i = 0; i < acm->rx_buflimit; i++) { |
468 | list_add(&(acm->ru[i].list), &acm->spare_read_urbs); | 477 | list_add(&(acm->ru[i].list), &acm->spare_read_urbs); |
469 | } | 478 | } |
470 | for (i = 0; i < ACM_NRB; i++) { | 479 | for (i = 0; i < acm->rx_buflimit; i++) { |
471 | list_add(&(acm->rb[i].list), &acm->spare_read_bufs); | 480 | list_add(&(acm->rb[i].list), &acm->spare_read_bufs); |
472 | } | 481 | } |
473 | 482 | ||
@@ -488,14 +497,15 @@ bail_out: | |||
488 | 497 | ||
489 | static void acm_tty_unregister(struct acm *acm) | 498 | static void acm_tty_unregister(struct acm *acm) |
490 | { | 499 | { |
491 | int i; | 500 | int i,nr; |
492 | 501 | ||
502 | nr = acm->rx_buflimit; | ||
493 | tty_unregister_device(acm_tty_driver, acm->minor); | 503 | tty_unregister_device(acm_tty_driver, acm->minor); |
494 | usb_put_intf(acm->control); | 504 | usb_put_intf(acm->control); |
495 | acm_table[acm->minor] = NULL; | 505 | acm_table[acm->minor] = NULL; |
496 | usb_free_urb(acm->ctrlurb); | 506 | usb_free_urb(acm->ctrlurb); |
497 | usb_free_urb(acm->writeurb); | 507 | usb_free_urb(acm->writeurb); |
498 | for (i = 0; i < ACM_NRU; i++) | 508 | for (i = 0; i < nr; i++) |
499 | usb_free_urb(acm->ru[i].urb); | 509 | usb_free_urb(acm->ru[i].urb); |
500 | kfree(acm); | 510 | kfree(acm); |
501 | } | 511 | } |
@@ -503,18 +513,19 @@ static void acm_tty_unregister(struct acm *acm) | |||
503 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) | 513 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) |
504 | { | 514 | { |
505 | struct acm *acm = tty->driver_data; | 515 | struct acm *acm = tty->driver_data; |
506 | int i; | 516 | int i,nr; |
507 | 517 | ||
508 | if (!acm || !acm->used) | 518 | if (!acm || !acm->used) |
509 | return; | 519 | return; |
510 | 520 | ||
521 | nr = acm->rx_buflimit; | ||
511 | mutex_lock(&open_mutex); | 522 | mutex_lock(&open_mutex); |
512 | if (!--acm->used) { | 523 | if (!--acm->used) { |
513 | if (acm->dev) { | 524 | if (acm->dev) { |
514 | acm_set_control(acm, acm->ctrlout = 0); | 525 | acm_set_control(acm, acm->ctrlout = 0); |
515 | usb_kill_urb(acm->ctrlurb); | 526 | usb_kill_urb(acm->ctrlurb); |
516 | usb_kill_urb(acm->writeurb); | 527 | usb_kill_urb(acm->writeurb); |
517 | for (i = 0; i < ACM_NRU; i++) | 528 | for (i = 0; i < nr; i++) |
518 | usb_kill_urb(acm->ru[i].urb); | 529 | usb_kill_urb(acm->ru[i].urb); |
519 | } else | 530 | } else |
520 | acm_tty_unregister(acm); | 531 | acm_tty_unregister(acm); |
@@ -576,7 +587,7 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty) | |||
576 | /* | 587 | /* |
577 | * This is inaccurate (overcounts), but it works. | 588 | * This is inaccurate (overcounts), but it works. |
578 | */ | 589 | */ |
579 | return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize; | 590 | return (ACM_NW - acm_wb_is_avail(acm)) * acm->writesize; |
580 | } | 591 | } |
581 | 592 | ||
582 | static void acm_tty_throttle(struct tty_struct *tty) | 593 | static void acm_tty_throttle(struct tty_struct *tty) |
@@ -712,7 +723,7 @@ static void acm_write_buffers_free(struct acm *acm) | |||
712 | int i; | 723 | int i; |
713 | struct acm_wb *wb; | 724 | struct acm_wb *wb; |
714 | 725 | ||
715 | for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { | 726 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { |
716 | usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah); | 727 | usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah); |
717 | } | 728 | } |
718 | } | 729 | } |
@@ -723,7 +734,7 @@ static int acm_write_buffers_alloc(struct acm *acm) | |||
723 | int i; | 734 | int i; |
724 | struct acm_wb *wb; | 735 | struct acm_wb *wb; |
725 | 736 | ||
726 | for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { | 737 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { |
727 | wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL, | 738 | wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL, |
728 | &wb->dmah); | 739 | &wb->dmah); |
729 | if (!wb->buf) { | 740 | if (!wb->buf) { |
@@ -760,10 +771,14 @@ static int acm_probe (struct usb_interface *intf, | |||
760 | int call_interface_num = -1; | 771 | int call_interface_num = -1; |
761 | int data_interface_num; | 772 | int data_interface_num; |
762 | unsigned long quirks; | 773 | unsigned long quirks; |
774 | int num_rx_buf; | ||
763 | int i; | 775 | int i; |
764 | 776 | ||
765 | /* handle quirks deadly to normal probing*/ | 777 | /* normal quirks */ |
766 | quirks = (unsigned long)id->driver_info; | 778 | quirks = (unsigned long)id->driver_info; |
779 | num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR; | ||
780 | |||
781 | /* handle quirks deadly to normal probing*/ | ||
767 | if (quirks == NO_UNION_NORMAL) { | 782 | if (quirks == NO_UNION_NORMAL) { |
768 | data_interface = usb_ifnum_to_if(usb_dev, 1); | 783 | data_interface = usb_ifnum_to_if(usb_dev, 1); |
769 | control_interface = usb_ifnum_to_if(usb_dev, 0); | 784 | control_interface = usb_ifnum_to_if(usb_dev, 0); |
@@ -900,7 +915,7 @@ skip_normal_probe: | |||
900 | } | 915 | } |
901 | 916 | ||
902 | ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); | 917 | ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); |
903 | readsize = le16_to_cpu(epread->wMaxPacketSize)*2; | 918 | readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2); |
904 | acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize); | 919 | acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize); |
905 | acm->control = control_interface; | 920 | acm->control = control_interface; |
906 | acm->data = data_interface; | 921 | acm->data = data_interface; |
@@ -909,6 +924,7 @@ skip_normal_probe: | |||
909 | acm->ctrl_caps = ac_management_function; | 924 | acm->ctrl_caps = ac_management_function; |
910 | acm->ctrlsize = ctrlsize; | 925 | acm->ctrlsize = ctrlsize; |
911 | acm->readsize = readsize; | 926 | acm->readsize = readsize; |
927 | acm->rx_buflimit = num_rx_buf; | ||
912 | acm->urb_task.func = acm_rx_tasklet; | 928 | acm->urb_task.func = acm_rx_tasklet; |
913 | acm->urb_task.data = (unsigned long) acm; | 929 | acm->urb_task.data = (unsigned long) acm; |
914 | INIT_WORK(&acm->work, acm_softint, acm); | 930 | INIT_WORK(&acm->work, acm_softint, acm); |
@@ -935,7 +951,7 @@ skip_normal_probe: | |||
935 | dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); | 951 | dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); |
936 | goto alloc_fail5; | 952 | goto alloc_fail5; |
937 | } | 953 | } |
938 | for (i = 0; i < ACM_NRU; i++) { | 954 | for (i = 0; i < num_rx_buf; i++) { |
939 | struct acm_ru *rcv = &(acm->ru[i]); | 955 | struct acm_ru *rcv = &(acm->ru[i]); |
940 | 956 | ||
941 | if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { | 957 | if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { |
@@ -946,10 +962,9 @@ skip_normal_probe: | |||
946 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 962 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
947 | rcv->instance = acm; | 963 | rcv->instance = acm; |
948 | } | 964 | } |
949 | for (i = 0; i < ACM_NRB; i++) { | 965 | for (i = 0; i < num_rx_buf; i++) { |
950 | struct acm_rb *buf = &(acm->rb[i]); | 966 | struct acm_rb *buf = &(acm->rb[i]); |
951 | 967 | ||
952 | // Using usb_buffer_alloc instead of kmalloc as Oliver suggested | ||
953 | if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) { | 968 | if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) { |
954 | dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n"); | 969 | dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n"); |
955 | goto alloc_fail7; | 970 | goto alloc_fail7; |
@@ -988,9 +1003,9 @@ skip_normal_probe: | |||
988 | return 0; | 1003 | return 0; |
989 | 1004 | ||
990 | alloc_fail7: | 1005 | alloc_fail7: |
991 | for (i = 0; i < ACM_NRB; i++) | 1006 | for (i = 0; i < num_rx_buf; i++) |
992 | usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); | 1007 | usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); |
993 | for (i = 0; i < ACM_NRU; i++) | 1008 | for (i = 0; i < num_rx_buf; i++) |
994 | usb_free_urb(acm->ru[i].urb); | 1009 | usb_free_urb(acm->ru[i].urb); |
995 | usb_free_urb(acm->ctrlurb); | 1010 | usb_free_urb(acm->ctrlurb); |
996 | alloc_fail5: | 1011 | alloc_fail5: |
@@ -1027,7 +1042,7 @@ static void acm_disconnect(struct usb_interface *intf) | |||
1027 | 1042 | ||
1028 | usb_kill_urb(acm->ctrlurb); | 1043 | usb_kill_urb(acm->ctrlurb); |
1029 | usb_kill_urb(acm->writeurb); | 1044 | usb_kill_urb(acm->writeurb); |
1030 | for (i = 0; i < ACM_NRU; i++) | 1045 | for (i = 0; i < acm->rx_buflimit; i++) |
1031 | usb_kill_urb(acm->ru[i].urb); | 1046 | usb_kill_urb(acm->ru[i].urb); |
1032 | 1047 | ||
1033 | INIT_LIST_HEAD(&acm->filled_read_bufs); | 1048 | INIT_LIST_HEAD(&acm->filled_read_bufs); |
@@ -1039,7 +1054,7 @@ static void acm_disconnect(struct usb_interface *intf) | |||
1039 | 1054 | ||
1040 | acm_write_buffers_free(acm); | 1055 | acm_write_buffers_free(acm); |
1041 | usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); | 1056 | usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); |
1042 | for (i = 0; i < ACM_NRB; i++) | 1057 | for (i = 0; i < acm->rx_buflimit; i++) |
1043 | usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); | 1058 | usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); |
1044 | 1059 | ||
1045 | usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf); | 1060 | usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf); |
@@ -1068,6 +1083,9 @@ static struct usb_device_id acm_ids[] = { | |||
1068 | { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ | 1083 | { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ |
1069 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1084 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1070 | }, | 1085 | }, |
1086 | { USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */ | ||
1087 | .driver_info = SINGLE_RX_URB, /* firmware bug */ | ||
1088 | }, | ||
1071 | /* control interfaces with various AT-command sets */ | 1089 | /* control interfaces with various AT-command sets */ |
1072 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1090 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1073 | USB_CDC_ACM_PROTO_AT_V25TER) }, | 1091 | USB_CDC_ACM_PROTO_AT_V25TER) }, |
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index fd2aaccdcbac..1bcaea32cfc1 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h | |||
@@ -56,11 +56,11 @@ | |||
56 | * in line disciplines. They ask for empty space amount, receive our URB size, | 56 | * in line disciplines. They ask for empty space amount, receive our URB size, |
57 | * and proceed to issue several 1-character writes, assuming they will fit. | 57 | * and proceed to issue several 1-character writes, assuming they will fit. |
58 | * The very first write takes a complete URB. Fortunately, this only happens | 58 | * The very first write takes a complete URB. Fortunately, this only happens |
59 | * when processing onlcr, so we only need 2 buffers. | 59 | * when processing onlcr, so we only need 2 buffers. These values must be |
60 | * powers of 2. | ||
60 | */ | 61 | */ |
61 | #define ACM_NWB 2 | 62 | #define ACM_NW 2 |
62 | #define ACM_NRU 16 | 63 | #define ACM_NR 16 |
63 | #define ACM_NRB 16 | ||
64 | 64 | ||
65 | struct acm_wb { | 65 | struct acm_wb { |
66 | unsigned char *buf; | 66 | unsigned char *buf; |
@@ -91,9 +91,10 @@ struct acm { | |||
91 | struct urb *ctrlurb, *writeurb; /* urbs */ | 91 | struct urb *ctrlurb, *writeurb; /* urbs */ |
92 | u8 *ctrl_buffer; /* buffers of urbs */ | 92 | u8 *ctrl_buffer; /* buffers of urbs */ |
93 | dma_addr_t ctrl_dma; /* dma handles of buffers */ | 93 | dma_addr_t ctrl_dma; /* dma handles of buffers */ |
94 | struct acm_wb wb[ACM_NWB]; | 94 | struct acm_wb wb[ACM_NW]; |
95 | struct acm_ru ru[ACM_NRU]; | 95 | struct acm_ru ru[ACM_NR]; |
96 | struct acm_rb rb[ACM_NRB]; | 96 | struct acm_rb rb[ACM_NR]; |
97 | int rx_buflimit; | ||
97 | int rx_endpoint; | 98 | int rx_endpoint; |
98 | spinlock_t read_lock; | 99 | spinlock_t read_lock; |
99 | struct list_head spare_read_urbs; | 100 | struct list_head spare_read_urbs; |
@@ -122,3 +123,4 @@ struct acm { | |||
122 | 123 | ||
123 | /* constants describing various quirks and errors */ | 124 | /* constants describing various quirks and errors */ |
124 | #define NO_UNION_NORMAL 1 | 125 | #define NO_UNION_NORMAL 1 |
126 | #define SINGLE_RX_URB 2 | ||
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 28329ddf187c..ec510922af63 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile | |||
@@ -3,7 +3,8 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ | 5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ |
6 | config.o file.o buffer.o sysfs.o devio.o notify.o | 6 | config.o file.o buffer.o sysfs.o endpoint.o \ |
7 | devio.o notify.o | ||
7 | 8 | ||
8 | ifeq ($(CONFIG_PCI),y) | 9 | ifeq ($(CONFIG_PCI),y) |
9 | usbcore-objs += hcd-pci.o | 10 | usbcore-objs += hcd-pci.o |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 545da37afca7..bcbeaf7101d1 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -515,19 +515,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig | |||
515 | 515 | ||
516 | static struct usb_device *usbdev_lookup_minor(int minor) | 516 | static struct usb_device *usbdev_lookup_minor(int minor) |
517 | { | 517 | { |
518 | struct class_device *class_dev; | 518 | struct device *device; |
519 | struct usb_device *dev = NULL; | 519 | struct usb_device *udev = NULL; |
520 | 520 | ||
521 | down(&usb_device_class->sem); | 521 | down(&usb_device_class->sem); |
522 | list_for_each_entry(class_dev, &usb_device_class->children, node) { | 522 | list_for_each_entry(device, &usb_device_class->devices, node) { |
523 | if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { | 523 | if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { |
524 | dev = class_dev->class_data; | 524 | udev = device->platform_data; |
525 | break; | 525 | break; |
526 | } | 526 | } |
527 | } | 527 | } |
528 | up(&usb_device_class->sem); | 528 | up(&usb_device_class->sem); |
529 | 529 | ||
530 | return dev; | 530 | return udev; |
531 | }; | 531 | }; |
532 | 532 | ||
533 | /* | 533 | /* |
@@ -823,8 +823,7 @@ static int proc_connectinfo(struct dev_state *ps, void __user *arg) | |||
823 | 823 | ||
824 | static int proc_resetdevice(struct dev_state *ps) | 824 | static int proc_resetdevice(struct dev_state *ps) |
825 | { | 825 | { |
826 | return usb_reset_device(ps->dev); | 826 | return usb_reset_composite_device(ps->dev, NULL); |
827 | |||
828 | } | 827 | } |
829 | 828 | ||
830 | static int proc_setintf(struct dev_state *ps, void __user *arg) | 829 | static int proc_setintf(struct dev_state *ps, void __user *arg) |
@@ -923,8 +922,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
923 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | 922 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) |
924 | != USB_ENDPOINT_XFER_CONTROL) | 923 | != USB_ENDPOINT_XFER_CONTROL) |
925 | return -EINVAL; | 924 | return -EINVAL; |
926 | /* min 8 byte setup packet, max arbitrary */ | 925 | /* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */ |
927 | if (uurb->buffer_length < 8 || uurb->buffer_length > PAGE_SIZE) | 926 | if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE)) |
928 | return -EINVAL; | 927 | return -EINVAL; |
929 | if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL))) | 928 | if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL))) |
930 | return -ENOMEM; | 929 | return -ENOMEM; |
@@ -982,7 +981,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
982 | return -EFAULT; | 981 | return -EFAULT; |
983 | } | 982 | } |
984 | for (totlen = u = 0; u < uurb->number_of_packets; u++) { | 983 | for (totlen = u = 0; u < uurb->number_of_packets; u++) { |
985 | if (isopkt[u].length > 1023) { | 984 | /* arbitrary limit, sufficient for USB 2.0 high-bandwidth iso */ |
985 | if (isopkt[u].length > 8192) { | ||
986 | kfree(isopkt); | 986 | kfree(isopkt); |
987 | return -EINVAL; | 987 | return -EINVAL; |
988 | } | 988 | } |
@@ -1576,16 +1576,16 @@ static void usbdev_add(struct usb_device *dev) | |||
1576 | { | 1576 | { |
1577 | int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); | 1577 | int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); |
1578 | 1578 | ||
1579 | dev->class_dev = class_device_create(usb_device_class, NULL, | 1579 | dev->usbfs_dev = device_create(usb_device_class, &dev->dev, |
1580 | MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev, | 1580 | MKDEV(USB_DEVICE_MAJOR, minor), |
1581 | "usbdev%d.%d", dev->bus->busnum, dev->devnum); | 1581 | "usbdev%d.%d", dev->bus->busnum, dev->devnum); |
1582 | 1582 | ||
1583 | dev->class_dev->class_data = dev; | 1583 | dev->usbfs_dev->platform_data = dev; |
1584 | } | 1584 | } |
1585 | 1585 | ||
1586 | static void usbdev_remove(struct usb_device *dev) | 1586 | static void usbdev_remove(struct usb_device *dev) |
1587 | { | 1587 | { |
1588 | class_device_unregister(dev->class_dev); | 1588 | device_unregister(dev->usbfs_dev); |
1589 | } | 1589 | } |
1590 | 1590 | ||
1591 | static int usbdev_notify(struct notifier_block *self, unsigned long action, | 1591 | static int usbdev_notify(struct notifier_block *self, unsigned long action, |
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c new file mode 100644 index 000000000000..247b5a4913a8 --- /dev/null +++ b/drivers/usb/core/endpoint.c | |||
@@ -0,0 +1,275 @@ | |||
1 | /* | ||
2 | * drivers/usb/core/endpoint.c | ||
3 | * | ||
4 | * (C) Copyright 2002,2004,2006 Greg Kroah-Hartman | ||
5 | * (C) Copyright 2002,2004 IBM Corp. | ||
6 | * (C) Copyright 2006 Novell Inc. | ||
7 | * | ||
8 | * Endpoint sysfs stuff | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/usb.h> | ||
14 | #include "usb.h" | ||
15 | |||
16 | /* endpoint stuff */ | ||
17 | |||
18 | struct ep_device { | ||
19 | struct usb_endpoint_descriptor *desc; | ||
20 | struct usb_device *udev; | ||
21 | struct device dev; | ||
22 | }; | ||
23 | #define to_ep_device(_dev) \ | ||
24 | container_of(_dev, struct ep_device, dev) | ||
25 | |||
26 | struct ep_attribute { | ||
27 | struct attribute attr; | ||
28 | ssize_t (*show)(struct usb_device *, | ||
29 | struct usb_endpoint_descriptor *, char *); | ||
30 | }; | ||
31 | #define to_ep_attribute(_attr) \ | ||
32 | container_of(_attr, struct ep_attribute, attr) | ||
33 | |||
34 | #define usb_ep_attr(field, format_string) \ | ||
35 | static ssize_t show_ep_##field(struct device *dev, \ | ||
36 | struct device_attribute *attr, \ | ||
37 | char *buf) \ | ||
38 | { \ | ||
39 | struct ep_device *ep = to_ep_device(dev); \ | ||
40 | return sprintf(buf, format_string, ep->desc->field); \ | ||
41 | } \ | ||
42 | static DEVICE_ATTR(field, S_IRUGO, show_ep_##field, NULL); | ||
43 | |||
44 | usb_ep_attr(bLength, "%02x\n") | ||
45 | usb_ep_attr(bEndpointAddress, "%02x\n") | ||
46 | usb_ep_attr(bmAttributes, "%02x\n") | ||
47 | usb_ep_attr(bInterval, "%02x\n") | ||
48 | |||
49 | static ssize_t show_ep_wMaxPacketSize(struct device *dev, | ||
50 | struct device_attribute *attr, char *buf) | ||
51 | { | ||
52 | struct ep_device *ep = to_ep_device(dev); | ||
53 | return sprintf(buf, "%04x\n", | ||
54 | le16_to_cpu(ep->desc->wMaxPacketSize) & 0x07ff); | ||
55 | } | ||
56 | static DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL); | ||
57 | |||
58 | static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, | ||
59 | char *buf) | ||
60 | { | ||
61 | struct ep_device *ep = to_ep_device(dev); | ||
62 | char *type = "unknown"; | ||
63 | |||
64 | switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | ||
65 | case USB_ENDPOINT_XFER_CONTROL: | ||
66 | type = "Control"; | ||
67 | break; | ||
68 | case USB_ENDPOINT_XFER_ISOC: | ||
69 | type = "Isoc"; | ||
70 | break; | ||
71 | case USB_ENDPOINT_XFER_BULK: | ||
72 | type = "Bulk"; | ||
73 | break; | ||
74 | case USB_ENDPOINT_XFER_INT: | ||
75 | type = "Interrupt"; | ||
76 | break; | ||
77 | } | ||
78 | return sprintf(buf, "%s\n", type); | ||
79 | } | ||
80 | static DEVICE_ATTR(type, S_IRUGO, show_ep_type, NULL); | ||
81 | |||
82 | static ssize_t show_ep_interval(struct device *dev, | ||
83 | struct device_attribute *attr, char *buf) | ||
84 | { | ||
85 | struct ep_device *ep = to_ep_device(dev); | ||
86 | char unit; | ||
87 | unsigned interval = 0; | ||
88 | unsigned in; | ||
89 | |||
90 | in = (ep->desc->bEndpointAddress & USB_DIR_IN); | ||
91 | |||
92 | switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | ||
93 | case USB_ENDPOINT_XFER_CONTROL: | ||
94 | if (ep->udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ | ||
95 | interval = ep->desc->bInterval; | ||
96 | break; | ||
97 | case USB_ENDPOINT_XFER_ISOC: | ||
98 | interval = 1 << (ep->desc->bInterval - 1); | ||
99 | break; | ||
100 | case USB_ENDPOINT_XFER_BULK: | ||
101 | if (ep->udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ | ||
102 | interval = ep->desc->bInterval; | ||
103 | break; | ||
104 | case USB_ENDPOINT_XFER_INT: | ||
105 | if (ep->udev->speed == USB_SPEED_HIGH) | ||
106 | interval = 1 << (ep->desc->bInterval - 1); | ||
107 | else | ||
108 | interval = ep->desc->bInterval; | ||
109 | break; | ||
110 | } | ||
111 | interval *= (ep->udev->speed == USB_SPEED_HIGH) ? 125 : 1000; | ||
112 | if (interval % 1000) | ||
113 | unit = 'u'; | ||
114 | else { | ||
115 | unit = 'm'; | ||
116 | interval /= 1000; | ||
117 | } | ||
118 | |||
119 | return sprintf(buf, "%d%cs\n", interval, unit); | ||
120 | } | ||
121 | static DEVICE_ATTR(interval, S_IRUGO, show_ep_interval, NULL); | ||
122 | |||
123 | static ssize_t show_ep_direction(struct device *dev, | ||
124 | struct device_attribute *attr, char *buf) | ||
125 | { | ||
126 | struct ep_device *ep = to_ep_device(dev); | ||
127 | char *direction; | ||
128 | |||
129 | if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
130 | USB_ENDPOINT_XFER_CONTROL) | ||
131 | direction = "both"; | ||
132 | else if (ep->desc->bEndpointAddress & USB_DIR_IN) | ||
133 | direction = "in"; | ||
134 | else | ||
135 | direction = "out"; | ||
136 | return sprintf(buf, "%s\n", direction); | ||
137 | } | ||
138 | static DEVICE_ATTR(direction, S_IRUGO, show_ep_direction, NULL); | ||
139 | |||
140 | static struct attribute *ep_dev_attrs[] = { | ||
141 | &dev_attr_bLength.attr, | ||
142 | &dev_attr_bEndpointAddress.attr, | ||
143 | &dev_attr_bmAttributes.attr, | ||
144 | &dev_attr_bInterval.attr, | ||
145 | &dev_attr_wMaxPacketSize.attr, | ||
146 | &dev_attr_interval.attr, | ||
147 | &dev_attr_type.attr, | ||
148 | &dev_attr_direction.attr, | ||
149 | NULL, | ||
150 | }; | ||
151 | static struct attribute_group ep_dev_attr_grp = { | ||
152 | .attrs = ep_dev_attrs, | ||
153 | }; | ||
154 | |||
155 | static struct endpoint_class { | ||
156 | struct kref kref; | ||
157 | struct class *class; | ||
158 | } *ep_class; | ||
159 | |||
160 | static int init_endpoint_class(void) | ||
161 | { | ||
162 | int result = 0; | ||
163 | |||
164 | if (ep_class != NULL) { | ||
165 | kref_get(&ep_class->kref); | ||
166 | goto exit; | ||
167 | } | ||
168 | |||
169 | ep_class = kmalloc(sizeof(*ep_class), GFP_KERNEL); | ||
170 | if (!ep_class) { | ||
171 | result = -ENOMEM; | ||
172 | goto exit; | ||
173 | } | ||
174 | |||
175 | kref_init(&ep_class->kref); | ||
176 | ep_class->class = class_create(THIS_MODULE, "usb_endpoint"); | ||
177 | if (IS_ERR(ep_class->class)) { | ||
178 | result = IS_ERR(ep_class->class); | ||
179 | kfree(ep_class); | ||
180 | ep_class = NULL; | ||
181 | goto exit; | ||
182 | } | ||
183 | |||
184 | exit: | ||
185 | return result; | ||
186 | } | ||
187 | |||
188 | static void release_endpoint_class(struct kref *kref) | ||
189 | { | ||
190 | /* Ok, we cheat as we know we only have one ep_class */ | ||
191 | class_destroy(ep_class->class); | ||
192 | kfree(ep_class); | ||
193 | ep_class = NULL; | ||
194 | } | ||
195 | |||
196 | static void destroy_endpoint_class(void) | ||
197 | { | ||
198 | if (ep_class) | ||
199 | kref_put(&ep_class->kref, release_endpoint_class); | ||
200 | } | ||
201 | |||
202 | static void ep_device_release(struct device *dev) | ||
203 | { | ||
204 | struct ep_device *ep_dev = to_ep_device(dev); | ||
205 | |||
206 | dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id); | ||
207 | kfree(ep_dev); | ||
208 | } | ||
209 | |||
210 | void usb_create_ep_files(struct device *parent, | ||
211 | struct usb_host_endpoint *endpoint, | ||
212 | struct usb_device *udev) | ||
213 | { | ||
214 | char name[8]; | ||
215 | struct ep_device *ep_dev; | ||
216 | int minor; | ||
217 | int retval; | ||
218 | |||
219 | retval = init_endpoint_class(); | ||
220 | if (retval) | ||
221 | goto exit; | ||
222 | |||
223 | ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL); | ||
224 | if (!ep_dev) { | ||
225 | retval = -ENOMEM; | ||
226 | goto exit; | ||
227 | } | ||
228 | |||
229 | /* fun calculation to determine the minor of this endpoint */ | ||
230 | minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1); | ||
231 | |||
232 | ep_dev->desc = &endpoint->desc; | ||
233 | ep_dev->udev = udev; | ||
234 | ep_dev->dev.devt = MKDEV(442, minor); // FIXME fake number... | ||
235 | ep_dev->dev.class = ep_class->class; | ||
236 | ep_dev->dev.parent = parent; | ||
237 | ep_dev->dev.release = ep_device_release; | ||
238 | snprintf(ep_dev->dev.bus_id, BUS_ID_SIZE, "usbdev%d.%d_ep%02x", | ||
239 | udev->bus->busnum, udev->devnum, | ||
240 | endpoint->desc.bEndpointAddress); | ||
241 | |||
242 | retval = device_register(&ep_dev->dev); | ||
243 | if (retval) | ||
244 | goto error; | ||
245 | sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); | ||
246 | |||
247 | endpoint->ep_dev = ep_dev; | ||
248 | |||
249 | /* create the symlink to the old-style "ep_XX" directory */ | ||
250 | sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); | ||
251 | sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name); | ||
252 | |||
253 | exit: | ||
254 | return; | ||
255 | error: | ||
256 | kfree(ep_dev); | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | void usb_remove_ep_files(struct usb_host_endpoint *endpoint) | ||
261 | { | ||
262 | |||
263 | if (endpoint->ep_dev) { | ||
264 | char name[8]; | ||
265 | |||
266 | sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); | ||
267 | sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name); | ||
268 | sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp); | ||
269 | device_unregister(&endpoint->ep_dev->dev); | ||
270 | endpoint->ep_dev = NULL; | ||
271 | } | ||
272 | destroy_endpoint_class(); | ||
273 | } | ||
274 | |||
275 | |||
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index b263a54a13c0..f65b193cde3d 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c | |||
@@ -61,33 +61,66 @@ static struct file_operations usb_fops = { | |||
61 | .open = usb_open, | 61 | .open = usb_open, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static struct class *usb_class; | 64 | static struct usb_class { |
65 | struct kref kref; | ||
66 | struct class *class; | ||
67 | } *usb_class; | ||
65 | 68 | ||
66 | int usb_major_init(void) | 69 | static int init_usb_class(void) |
67 | { | 70 | { |
68 | int error; | 71 | int result = 0; |
69 | 72 | ||
70 | error = register_chrdev(USB_MAJOR, "usb", &usb_fops); | 73 | if (usb_class != NULL) { |
71 | if (error) { | 74 | kref_get(&usb_class->kref); |
72 | err("unable to get major %d for usb devices", USB_MAJOR); | 75 | goto exit; |
73 | goto out; | 76 | } |
77 | |||
78 | usb_class = kmalloc(sizeof(*usb_class), GFP_KERNEL); | ||
79 | if (!usb_class) { | ||
80 | result = -ENOMEM; | ||
81 | goto exit; | ||
74 | } | 82 | } |
75 | 83 | ||
76 | usb_class = class_create(THIS_MODULE, "usb"); | 84 | kref_init(&usb_class->kref); |
77 | if (IS_ERR(usb_class)) { | 85 | usb_class->class = class_create(THIS_MODULE, "usb"); |
78 | error = PTR_ERR(usb_class); | 86 | if (IS_ERR(usb_class->class)) { |
87 | result = IS_ERR(usb_class->class); | ||
79 | err("class_create failed for usb devices"); | 88 | err("class_create failed for usb devices"); |
80 | unregister_chrdev(USB_MAJOR, "usb"); | 89 | kfree(usb_class); |
81 | goto out; | 90 | usb_class = NULL; |
82 | } | 91 | } |
83 | 92 | ||
84 | out: | 93 | exit: |
94 | return result; | ||
95 | } | ||
96 | |||
97 | static void release_usb_class(struct kref *kref) | ||
98 | { | ||
99 | /* Ok, we cheat as we know we only have one usb_class */ | ||
100 | class_destroy(usb_class->class); | ||
101 | kfree(usb_class); | ||
102 | usb_class = NULL; | ||
103 | } | ||
104 | |||
105 | static void destroy_usb_class(void) | ||
106 | { | ||
107 | if (usb_class) | ||
108 | kref_put(&usb_class->kref, release_usb_class); | ||
109 | } | ||
110 | |||
111 | int usb_major_init(void) | ||
112 | { | ||
113 | int error; | ||
114 | |||
115 | error = register_chrdev(USB_MAJOR, "usb", &usb_fops); | ||
116 | if (error) | ||
117 | err("unable to get major %d for usb devices", USB_MAJOR); | ||
118 | |||
85 | return error; | 119 | return error; |
86 | } | 120 | } |
87 | 121 | ||
88 | void usb_major_cleanup(void) | 122 | void usb_major_cleanup(void) |
89 | { | 123 | { |
90 | class_destroy(usb_class); | ||
91 | unregister_chrdev(USB_MAJOR, "usb"); | 124 | unregister_chrdev(USB_MAJOR, "usb"); |
92 | } | 125 | } |
93 | 126 | ||
@@ -149,6 +182,10 @@ int usb_register_dev(struct usb_interface *intf, | |||
149 | if (retval) | 182 | if (retval) |
150 | goto exit; | 183 | goto exit; |
151 | 184 | ||
185 | retval = init_usb_class(); | ||
186 | if (retval) | ||
187 | goto exit; | ||
188 | |||
152 | intf->minor = minor; | 189 | intf->minor = minor; |
153 | 190 | ||
154 | /* create a usb class device for this usb interface */ | 191 | /* create a usb class device for this usb interface */ |
@@ -158,14 +195,13 @@ int usb_register_dev(struct usb_interface *intf, | |||
158 | ++temp; | 195 | ++temp; |
159 | else | 196 | else |
160 | temp = name; | 197 | temp = name; |
161 | intf->class_dev = class_device_create(usb_class, NULL, | 198 | intf->usb_dev = device_create(usb_class->class, &intf->dev, |
162 | MKDEV(USB_MAJOR, minor), | 199 | MKDEV(USB_MAJOR, minor), "%s", temp); |
163 | &intf->dev, "%s", temp); | 200 | if (IS_ERR(intf->usb_dev)) { |
164 | if (IS_ERR(intf->class_dev)) { | ||
165 | spin_lock (&minor_lock); | 201 | spin_lock (&minor_lock); |
166 | usb_minors[intf->minor] = NULL; | 202 | usb_minors[intf->minor] = NULL; |
167 | spin_unlock (&minor_lock); | 203 | spin_unlock (&minor_lock); |
168 | retval = PTR_ERR(intf->class_dev); | 204 | retval = PTR_ERR(intf->usb_dev); |
169 | } | 205 | } |
170 | exit: | 206 | exit: |
171 | return retval; | 207 | return retval; |
@@ -206,9 +242,10 @@ void usb_deregister_dev(struct usb_interface *intf, | |||
206 | spin_unlock (&minor_lock); | 242 | spin_unlock (&minor_lock); |
207 | 243 | ||
208 | snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); | 244 | snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); |
209 | class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor)); | 245 | device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); |
210 | intf->class_dev = NULL; | 246 | intf->usb_dev = NULL; |
211 | intf->minor = -1; | 247 | intf->minor = -1; |
248 | destroy_usb_class(); | ||
212 | } | 249 | } |
213 | EXPORT_SYMBOL(usb_deregister_dev); | 250 | EXPORT_SYMBOL(usb_deregister_dev); |
214 | 251 | ||
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index e2e00ba4e1e6..4bf914d00a14 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1826,24 +1826,16 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1826 | 1826 | ||
1827 | /* enable irqs just before we start the controller */ | 1827 | /* enable irqs just before we start the controller */ |
1828 | if (hcd->driver->irq) { | 1828 | if (hcd->driver->irq) { |
1829 | char buf[8], *bufp = buf; | ||
1830 | |||
1831 | #ifdef __sparc__ | ||
1832 | bufp = __irq_itoa(irqnum); | ||
1833 | #else | ||
1834 | sprintf(buf, "%d", irqnum); | ||
1835 | #endif | ||
1836 | |||
1837 | snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", | 1829 | snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", |
1838 | hcd->driver->description, hcd->self.busnum); | 1830 | hcd->driver->description, hcd->self.busnum); |
1839 | if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags, | 1831 | if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags, |
1840 | hcd->irq_descr, hcd)) != 0) { | 1832 | hcd->irq_descr, hcd)) != 0) { |
1841 | dev_err(hcd->self.controller, | 1833 | dev_err(hcd->self.controller, |
1842 | "request interrupt %s failed\n", bufp); | 1834 | "request interrupt %d failed\n", irqnum); |
1843 | goto err_request_irq; | 1835 | goto err_request_irq; |
1844 | } | 1836 | } |
1845 | hcd->irq = irqnum; | 1837 | hcd->irq = irqnum; |
1846 | dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp, | 1838 | dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum, |
1847 | (hcd->driver->flags & HCD_MEMORY) ? | 1839 | (hcd->driver->flags & HCD_MEMORY) ? |
1848 | "io mem" : "io base", | 1840 | "io mem" : "io base", |
1849 | (unsigned long long)hcd->rsrc_start); | 1841 | (unsigned long long)hcd->rsrc_start); |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 90b8d43c6b33..e1731ff8af4d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -432,15 +432,22 @@ static void hub_power_on(struct usb_hub *hub) | |||
432 | { | 432 | { |
433 | int port1; | 433 | int port1; |
434 | unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; | 434 | unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; |
435 | u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); | 435 | u16 wHubCharacteristics = |
436 | 436 | le16_to_cpu(hub->descriptor->wHubCharacteristics); | |
437 | /* if hub supports power switching, enable power on each port */ | 437 | |
438 | if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) { | 438 | /* Enable power on each port. Some hubs have reserved values |
439 | * of LPSM (> 2) in their descriptors, even though they are | ||
440 | * USB 2.0 hubs. Some hubs do not implement port-power switching | ||
441 | * but only emulate it. In all cases, the ports won't work | ||
442 | * unless we send these messages to the hub. | ||
443 | */ | ||
444 | if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) | ||
439 | dev_dbg(hub->intfdev, "enabling power on all ports\n"); | 445 | dev_dbg(hub->intfdev, "enabling power on all ports\n"); |
440 | for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) | 446 | else |
441 | set_port_feature(hub->hdev, port1, | 447 | dev_dbg(hub->intfdev, "trying to enable port power on " |
442 | USB_PORT_FEAT_POWER); | 448 | "non-switchable hub\n"); |
443 | } | 449 | for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) |
450 | set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); | ||
444 | 451 | ||
445 | /* Wait at least 100 msec for power to become stable */ | 452 | /* Wait at least 100 msec for power to become stable */ |
446 | msleep(max(pgood_delay, (unsigned) 100)); | 453 | msleep(max(pgood_delay, (unsigned) 100)); |
@@ -518,15 +525,16 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) | |||
518 | 525 | ||
519 | 526 | ||
520 | /* caller has locked the hub device */ | 527 | /* caller has locked the hub device */ |
521 | static void hub_pre_reset(struct usb_hub *hub, int disable_ports) | 528 | static void hub_pre_reset(struct usb_interface *intf) |
522 | { | 529 | { |
530 | struct usb_hub *hub = usb_get_intfdata(intf); | ||
523 | struct usb_device *hdev = hub->hdev; | 531 | struct usb_device *hdev = hub->hdev; |
524 | int port1; | 532 | int port1; |
525 | 533 | ||
526 | for (port1 = 1; port1 <= hdev->maxchild; ++port1) { | 534 | for (port1 = 1; port1 <= hdev->maxchild; ++port1) { |
527 | if (hdev->children[port1 - 1]) { | 535 | if (hdev->children[port1 - 1]) { |
528 | usb_disconnect(&hdev->children[port1 - 1]); | 536 | usb_disconnect(&hdev->children[port1 - 1]); |
529 | if (disable_ports) | 537 | if (hub->error == 0) |
530 | hub_port_disable(hub, port1, 0); | 538 | hub_port_disable(hub, port1, 0); |
531 | } | 539 | } |
532 | } | 540 | } |
@@ -534,8 +542,10 @@ static void hub_pre_reset(struct usb_hub *hub, int disable_ports) | |||
534 | } | 542 | } |
535 | 543 | ||
536 | /* caller has locked the hub device */ | 544 | /* caller has locked the hub device */ |
537 | static void hub_post_reset(struct usb_hub *hub) | 545 | static void hub_post_reset(struct usb_interface *intf) |
538 | { | 546 | { |
547 | struct usb_hub *hub = usb_get_intfdata(intf); | ||
548 | |||
539 | hub_activate(hub); | 549 | hub_activate(hub); |
540 | hub_power_on(hub); | 550 | hub_power_on(hub); |
541 | } | 551 | } |
@@ -795,15 +805,16 @@ static void hub_disconnect(struct usb_interface *intf) | |||
795 | struct usb_hub *hub = usb_get_intfdata (intf); | 805 | struct usb_hub *hub = usb_get_intfdata (intf); |
796 | struct usb_device *hdev; | 806 | struct usb_device *hdev; |
797 | 807 | ||
808 | /* Disconnect all children and quiesce the hub */ | ||
809 | hub->error = 0; | ||
810 | hub_pre_reset(intf); | ||
811 | |||
798 | usb_set_intfdata (intf, NULL); | 812 | usb_set_intfdata (intf, NULL); |
799 | hdev = hub->hdev; | 813 | hdev = hub->hdev; |
800 | 814 | ||
801 | if (hdev->speed == USB_SPEED_HIGH) | 815 | if (hdev->speed == USB_SPEED_HIGH) |
802 | highspeed_hubs--; | 816 | highspeed_hubs--; |
803 | 817 | ||
804 | /* Disconnect all children and quiesce the hub */ | ||
805 | hub_pre_reset(hub, 1); | ||
806 | |||
807 | usb_free_urb(hub->urb); | 818 | usb_free_urb(hub->urb); |
808 | hub->urb = NULL; | 819 | hub->urb = NULL; |
809 | 820 | ||
@@ -1169,6 +1180,7 @@ static int choose_configuration(struct usb_device *udev) | |||
1169 | { | 1180 | { |
1170 | int i; | 1181 | int i; |
1171 | int num_configs; | 1182 | int num_configs; |
1183 | int insufficient_power = 0; | ||
1172 | struct usb_host_config *c, *best; | 1184 | struct usb_host_config *c, *best; |
1173 | 1185 | ||
1174 | best = NULL; | 1186 | best = NULL; |
@@ -1221,8 +1233,10 @@ static int choose_configuration(struct usb_device *udev) | |||
1221 | */ | 1233 | */ |
1222 | 1234 | ||
1223 | /* Rule out configs that draw too much bus current */ | 1235 | /* Rule out configs that draw too much bus current */ |
1224 | if (c->desc.bMaxPower * 2 > udev->bus_mA) | 1236 | if (c->desc.bMaxPower * 2 > udev->bus_mA) { |
1237 | insufficient_power++; | ||
1225 | continue; | 1238 | continue; |
1239 | } | ||
1226 | 1240 | ||
1227 | /* If the first config's first interface is COMM/2/0xff | 1241 | /* If the first config's first interface is COMM/2/0xff |
1228 | * (MSFT RNDIS), rule it out unless Linux has host-side | 1242 | * (MSFT RNDIS), rule it out unless Linux has host-side |
@@ -1231,7 +1245,7 @@ static int choose_configuration(struct usb_device *udev) | |||
1231 | && desc->bInterfaceClass == USB_CLASS_COMM | 1245 | && desc->bInterfaceClass == USB_CLASS_COMM |
1232 | && desc->bInterfaceSubClass == 2 | 1246 | && desc->bInterfaceSubClass == 2 |
1233 | && desc->bInterfaceProtocol == 0xff) { | 1247 | && desc->bInterfaceProtocol == 0xff) { |
1234 | #ifndef CONFIG_USB_NET_RNDIS | 1248 | #ifndef CONFIG_USB_NET_RNDIS_HOST |
1235 | continue; | 1249 | continue; |
1236 | #else | 1250 | #else |
1237 | best = c; | 1251 | best = c; |
@@ -1256,6 +1270,11 @@ static int choose_configuration(struct usb_device *udev) | |||
1256 | best = c; | 1270 | best = c; |
1257 | } | 1271 | } |
1258 | 1272 | ||
1273 | if (insufficient_power > 0) | ||
1274 | dev_info(&udev->dev, "rejected %d configuration%s " | ||
1275 | "due to insufficient available bus power\n", | ||
1276 | insufficient_power, plural(insufficient_power)); | ||
1277 | |||
1259 | if (best) { | 1278 | if (best) { |
1260 | i = best->desc.bConfigurationValue; | 1279 | i = best->desc.bConfigurationValue; |
1261 | dev_info(&udev->dev, | 1280 | dev_info(&udev->dev, |
@@ -2732,7 +2751,8 @@ static void hub_events(void) | |||
2732 | 2751 | ||
2733 | /* If the hub has died, clean up after it */ | 2752 | /* If the hub has died, clean up after it */ |
2734 | if (hdev->state == USB_STATE_NOTATTACHED) { | 2753 | if (hdev->state == USB_STATE_NOTATTACHED) { |
2735 | hub_pre_reset(hub, 0); | 2754 | hub->error = -ENODEV; |
2755 | hub_pre_reset(intf); | ||
2736 | goto loop; | 2756 | goto loop; |
2737 | } | 2757 | } |
2738 | 2758 | ||
@@ -2744,7 +2764,7 @@ static void hub_events(void) | |||
2744 | dev_dbg (hub_dev, "resetting for error %d\n", | 2764 | dev_dbg (hub_dev, "resetting for error %d\n", |
2745 | hub->error); | 2765 | hub->error); |
2746 | 2766 | ||
2747 | ret = usb_reset_device(hdev); | 2767 | ret = usb_reset_composite_device(hdev, intf); |
2748 | if (ret) { | 2768 | if (ret) { |
2749 | dev_dbg (hub_dev, | 2769 | dev_dbg (hub_dev, |
2750 | "error resetting hub: %d\n", ret); | 2770 | "error resetting hub: %d\n", ret); |
@@ -2913,6 +2933,8 @@ static struct usb_driver hub_driver = { | |||
2913 | .disconnect = hub_disconnect, | 2933 | .disconnect = hub_disconnect, |
2914 | .suspend = hub_suspend, | 2934 | .suspend = hub_suspend, |
2915 | .resume = hub_resume, | 2935 | .resume = hub_resume, |
2936 | .pre_reset = hub_pre_reset, | ||
2937 | .post_reset = hub_post_reset, | ||
2916 | .ioctl = hub_ioctl, | 2938 | .ioctl = hub_ioctl, |
2917 | .id_table = hub_id_table, | 2939 | .id_table = hub_id_table, |
2918 | }; | 2940 | }; |
@@ -2992,9 +3014,9 @@ static int config_descriptors_changed(struct usb_device *udev) | |||
2992 | * usb_reset_device - perform a USB port reset to reinitialize a device | 3014 | * usb_reset_device - perform a USB port reset to reinitialize a device |
2993 | * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) | 3015 | * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) |
2994 | * | 3016 | * |
2995 | * WARNING - don't reset any device unless drivers for all of its | 3017 | * WARNING - don't use this routine to reset a composite device |
2996 | * interfaces are expecting that reset! Maybe some driver->reset() | 3018 | * (one with multiple interfaces owned by separate drivers)! |
2997 | * method should eventually help ensure sufficient cooperation. | 3019 | * Use usb_reset_composite_device() instead. |
2998 | * | 3020 | * |
2999 | * Do a port reset, reassign the device's address, and establish its | 3021 | * Do a port reset, reassign the device's address, and establish its |
3000 | * former operating configuration. If the reset fails, or the device's | 3022 | * former operating configuration. If the reset fails, or the device's |
@@ -3018,7 +3040,6 @@ int usb_reset_device(struct usb_device *udev) | |||
3018 | struct usb_device *parent_hdev = udev->parent; | 3040 | struct usb_device *parent_hdev = udev->parent; |
3019 | struct usb_hub *parent_hub; | 3041 | struct usb_hub *parent_hub; |
3020 | struct usb_device_descriptor descriptor = udev->descriptor; | 3042 | struct usb_device_descriptor descriptor = udev->descriptor; |
3021 | struct usb_hub *hub = NULL; | ||
3022 | int i, ret = 0; | 3043 | int i, ret = 0; |
3023 | int port1 = udev->portnum; | 3044 | int port1 = udev->portnum; |
3024 | 3045 | ||
@@ -3036,14 +3057,6 @@ int usb_reset_device(struct usb_device *udev) | |||
3036 | } | 3057 | } |
3037 | parent_hub = hdev_to_hub(parent_hdev); | 3058 | parent_hub = hdev_to_hub(parent_hdev); |
3038 | 3059 | ||
3039 | /* If we're resetting an active hub, take some special actions */ | ||
3040 | if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 && | ||
3041 | udev->actconfig->interface[0]->dev.driver == | ||
3042 | &hub_driver.driver && | ||
3043 | (hub = hdev_to_hub(udev)) != NULL) { | ||
3044 | hub_pre_reset(hub, 0); | ||
3045 | } | ||
3046 | |||
3047 | set_bit(port1, parent_hub->busy_bits); | 3060 | set_bit(port1, parent_hub->busy_bits); |
3048 | for (i = 0; i < SET_CONFIG_TRIES; ++i) { | 3061 | for (i = 0; i < SET_CONFIG_TRIES; ++i) { |
3049 | 3062 | ||
@@ -3102,11 +3115,87 @@ int usb_reset_device(struct usb_device *udev) | |||
3102 | } | 3115 | } |
3103 | 3116 | ||
3104 | done: | 3117 | done: |
3105 | if (hub) | ||
3106 | hub_post_reset(hub); | ||
3107 | return 0; | 3118 | return 0; |
3108 | 3119 | ||
3109 | re_enumerate: | 3120 | re_enumerate: |
3110 | hub_port_logical_disconnect(parent_hub, port1); | 3121 | hub_port_logical_disconnect(parent_hub, port1); |
3111 | return -ENODEV; | 3122 | return -ENODEV; |
3112 | } | 3123 | } |
3124 | |||
3125 | /** | ||
3126 | * usb_reset_composite_device - warn interface drivers and perform a USB port reset | ||
3127 | * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) | ||
3128 | * @iface: interface bound to the driver making the request (optional) | ||
3129 | * | ||
3130 | * Warns all drivers bound to registered interfaces (using their pre_reset | ||
3131 | * method), performs the port reset, and then lets the drivers know that | ||
3132 | * the reset is over (using their post_reset method). | ||
3133 | * | ||
3134 | * Return value is the same as for usb_reset_device(). | ||
3135 | * | ||
3136 | * The caller must own the device lock. For example, it's safe to use | ||
3137 | * this from a driver probe() routine after downloading new firmware. | ||
3138 | * For calls that might not occur during probe(), drivers should lock | ||
3139 | * the device using usb_lock_device_for_reset(). | ||
3140 | * | ||
3141 | * The interface locks are acquired during the pre_reset stage and released | ||
3142 | * during the post_reset stage. However if iface is not NULL and is | ||
3143 | * currently being probed, we assume that the caller already owns its | ||
3144 | * lock. | ||
3145 | */ | ||
3146 | int usb_reset_composite_device(struct usb_device *udev, | ||
3147 | struct usb_interface *iface) | ||
3148 | { | ||
3149 | int ret; | ||
3150 | struct usb_host_config *config = udev->actconfig; | ||
3151 | |||
3152 | if (udev->state == USB_STATE_NOTATTACHED || | ||
3153 | udev->state == USB_STATE_SUSPENDED) { | ||
3154 | dev_dbg(&udev->dev, "device reset not allowed in state %d\n", | ||
3155 | udev->state); | ||
3156 | return -EINVAL; | ||
3157 | } | ||
3158 | |||
3159 | if (iface && iface->condition != USB_INTERFACE_BINDING) | ||
3160 | iface = NULL; | ||
3161 | |||
3162 | if (config) { | ||
3163 | int i; | ||
3164 | struct usb_interface *cintf; | ||
3165 | struct usb_driver *drv; | ||
3166 | |||
3167 | for (i = 0; i < config->desc.bNumInterfaces; ++i) { | ||
3168 | cintf = config->interface[i]; | ||
3169 | if (cintf != iface) | ||
3170 | down(&cintf->dev.sem); | ||
3171 | if (device_is_registered(&cintf->dev) && | ||
3172 | cintf->dev.driver) { | ||
3173 | drv = to_usb_driver(cintf->dev.driver); | ||
3174 | if (drv->pre_reset) | ||
3175 | (drv->pre_reset)(cintf); | ||
3176 | } | ||
3177 | } | ||
3178 | } | ||
3179 | |||
3180 | ret = usb_reset_device(udev); | ||
3181 | |||
3182 | if (config) { | ||
3183 | int i; | ||
3184 | struct usb_interface *cintf; | ||
3185 | struct usb_driver *drv; | ||
3186 | |||
3187 | for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { | ||
3188 | cintf = config->interface[i]; | ||
3189 | if (device_is_registered(&cintf->dev) && | ||
3190 | cintf->dev.driver) { | ||
3191 | drv = to_usb_driver(cintf->dev.driver); | ||
3192 | if (drv->post_reset) | ||
3193 | (drv->post_reset)(cintf); | ||
3194 | } | ||
3195 | if (cintf != iface) | ||
3196 | up(&cintf->dev.sem); | ||
3197 | } | ||
3198 | } | ||
3199 | |||
3200 | return ret; | ||
3201 | } | ||
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 3cf945cc5b9a..bfc9b28a7242 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
@@ -543,10 +543,10 @@ static void fs_remove_file (struct dentry *dentry) | |||
543 | 543 | ||
544 | /* --------------------------------------------------------------------- */ | 544 | /* --------------------------------------------------------------------- */ |
545 | 545 | ||
546 | static struct super_block *usb_get_sb(struct file_system_type *fs_type, | 546 | static int usb_get_sb(struct file_system_type *fs_type, |
547 | int flags, const char *dev_name, void *data) | 547 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
548 | { | 548 | { |
549 | return get_sb_single(fs_type, flags, data, usbfs_fill_super); | 549 | return get_sb_single(fs_type, flags, data, usbfs_fill_super, mnt); |
550 | } | 550 | } |
551 | 551 | ||
552 | static struct file_system_type usb_fs_type = { | 552 | static struct file_system_type usb_fs_type = { |
@@ -569,7 +569,7 @@ static int create_special_files (void) | |||
569 | ignore_mount = 1; | 569 | ignore_mount = 1; |
570 | 570 | ||
571 | /* create the devices special file */ | 571 | /* create the devices special file */ |
572 | retval = simple_pin_fs("usbfs", &usbfs_mount, &usbfs_mount_count); | 572 | retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count); |
573 | if (retval) { | 573 | if (retval) { |
574 | err ("Unable to get usbfs mount"); | 574 | err ("Unable to get usbfs mount"); |
575 | goto exit; | 575 | goto exit; |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 08fb20f06f3e..8569600f3130 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -158,6 +158,37 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u | |||
158 | 158 | ||
159 | 159 | ||
160 | /** | 160 | /** |
161 | * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion | ||
162 | * @usb_dev: pointer to the usb device to send the message to | ||
163 | * @pipe: endpoint "pipe" to send the message to | ||
164 | * @data: pointer to the data to send | ||
165 | * @len: length in bytes of the data to send | ||
166 | * @actual_length: pointer to a location to put the actual length transferred in bytes | ||
167 | * @timeout: time in msecs to wait for the message to complete before | ||
168 | * timing out (if 0 the wait is forever) | ||
169 | * Context: !in_interrupt () | ||
170 | * | ||
171 | * This function sends a simple interrupt message to a specified endpoint and | ||
172 | * waits for the message to complete, or timeout. | ||
173 | * | ||
174 | * If successful, it returns 0, otherwise a negative error number. The number | ||
175 | * of actual bytes transferred will be stored in the actual_length paramater. | ||
176 | * | ||
177 | * Don't use this function from within an interrupt context, like a bottom half | ||
178 | * handler. If you need an asynchronous message, or need to send a message | ||
179 | * from within interrupt context, use usb_submit_urb() If a thread in your | ||
180 | * driver uses this call, make sure your disconnect() method can wait for it to | ||
181 | * complete. Since you don't have a handle on the URB used, you can't cancel | ||
182 | * the request. | ||
183 | */ | ||
184 | int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, | ||
185 | void *data, int len, int *actual_length, int timeout) | ||
186 | { | ||
187 | return usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout); | ||
188 | } | ||
189 | EXPORT_SYMBOL_GPL(usb_interrupt_msg); | ||
190 | |||
191 | /** | ||
161 | * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion | 192 | * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion |
162 | * @usb_dev: pointer to the usb device to send the message to | 193 | * @usb_dev: pointer to the usb device to send the message to |
163 | * @pipe: endpoint "pipe" to send the message to | 194 | * @pipe: endpoint "pipe" to send the message to |
@@ -1380,15 +1411,7 @@ free_interfaces: | |||
1380 | return ret; | 1411 | return ret; |
1381 | } | 1412 | } |
1382 | } | 1413 | } |
1383 | } | ||
1384 | |||
1385 | /* if it's already configured, clear out old state first. | ||
1386 | * getting rid of old interfaces means unbinding their drivers. | ||
1387 | */ | ||
1388 | if (dev->state != USB_STATE_ADDRESS) | ||
1389 | usb_disable_device (dev, 1); // Skip ep0 | ||
1390 | 1414 | ||
1391 | if (cp) { | ||
1392 | i = dev->bus_mA - cp->desc.bMaxPower * 2; | 1415 | i = dev->bus_mA - cp->desc.bMaxPower * 2; |
1393 | if (i < 0) | 1416 | if (i < 0) |
1394 | dev_warn(&dev->dev, "new config #%d exceeds power " | 1417 | dev_warn(&dev->dev, "new config #%d exceeds power " |
@@ -1396,84 +1419,91 @@ free_interfaces: | |||
1396 | configuration, -i); | 1419 | configuration, -i); |
1397 | } | 1420 | } |
1398 | 1421 | ||
1422 | /* if it's already configured, clear out old state first. | ||
1423 | * getting rid of old interfaces means unbinding their drivers. | ||
1424 | */ | ||
1425 | if (dev->state != USB_STATE_ADDRESS) | ||
1426 | usb_disable_device (dev, 1); // Skip ep0 | ||
1427 | |||
1399 | if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1428 | if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
1400 | USB_REQ_SET_CONFIGURATION, 0, configuration, 0, | 1429 | USB_REQ_SET_CONFIGURATION, 0, configuration, 0, |
1401 | NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) | 1430 | NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) { |
1402 | goto free_interfaces; | 1431 | |
1432 | /* All the old state is gone, so what else can we do? | ||
1433 | * The device is probably useless now anyway. | ||
1434 | */ | ||
1435 | cp = NULL; | ||
1436 | } | ||
1403 | 1437 | ||
1404 | dev->actconfig = cp; | 1438 | dev->actconfig = cp; |
1405 | if (!cp) | 1439 | if (!cp) { |
1406 | usb_set_device_state(dev, USB_STATE_ADDRESS); | 1440 | usb_set_device_state(dev, USB_STATE_ADDRESS); |
1407 | else { | 1441 | goto free_interfaces; |
1408 | usb_set_device_state(dev, USB_STATE_CONFIGURED); | 1442 | } |
1443 | usb_set_device_state(dev, USB_STATE_CONFIGURED); | ||
1409 | 1444 | ||
1410 | /* Initialize the new interface structures and the | 1445 | /* Initialize the new interface structures and the |
1411 | * hc/hcd/usbcore interface/endpoint state. | 1446 | * hc/hcd/usbcore interface/endpoint state. |
1412 | */ | 1447 | */ |
1413 | for (i = 0; i < nintf; ++i) { | 1448 | for (i = 0; i < nintf; ++i) { |
1414 | struct usb_interface_cache *intfc; | 1449 | struct usb_interface_cache *intfc; |
1415 | struct usb_interface *intf; | 1450 | struct usb_interface *intf; |
1416 | struct usb_host_interface *alt; | 1451 | struct usb_host_interface *alt; |
1417 | 1452 | ||
1418 | cp->interface[i] = intf = new_interfaces[i]; | 1453 | cp->interface[i] = intf = new_interfaces[i]; |
1419 | intfc = cp->intf_cache[i]; | 1454 | intfc = cp->intf_cache[i]; |
1420 | intf->altsetting = intfc->altsetting; | 1455 | intf->altsetting = intfc->altsetting; |
1421 | intf->num_altsetting = intfc->num_altsetting; | 1456 | intf->num_altsetting = intfc->num_altsetting; |
1422 | kref_get(&intfc->ref); | 1457 | kref_get(&intfc->ref); |
1423 | |||
1424 | alt = usb_altnum_to_altsetting(intf, 0); | ||
1425 | |||
1426 | /* No altsetting 0? We'll assume the first altsetting. | ||
1427 | * We could use a GetInterface call, but if a device is | ||
1428 | * so non-compliant that it doesn't have altsetting 0 | ||
1429 | * then I wouldn't trust its reply anyway. | ||
1430 | */ | ||
1431 | if (!alt) | ||
1432 | alt = &intf->altsetting[0]; | ||
1433 | |||
1434 | intf->cur_altsetting = alt; | ||
1435 | usb_enable_interface(dev, intf); | ||
1436 | intf->dev.parent = &dev->dev; | ||
1437 | intf->dev.driver = NULL; | ||
1438 | intf->dev.bus = &usb_bus_type; | ||
1439 | intf->dev.dma_mask = dev->dev.dma_mask; | ||
1440 | intf->dev.release = release_interface; | ||
1441 | device_initialize (&intf->dev); | ||
1442 | mark_quiesced(intf); | ||
1443 | sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", | ||
1444 | dev->bus->busnum, dev->devpath, | ||
1445 | configuration, | ||
1446 | alt->desc.bInterfaceNumber); | ||
1447 | } | ||
1448 | kfree(new_interfaces); | ||
1449 | 1458 | ||
1450 | if (cp->string == NULL) | 1459 | alt = usb_altnum_to_altsetting(intf, 0); |
1451 | cp->string = usb_cache_string(dev, | ||
1452 | cp->desc.iConfiguration); | ||
1453 | 1460 | ||
1454 | /* Now that all the interfaces are set up, register them | 1461 | /* No altsetting 0? We'll assume the first altsetting. |
1455 | * to trigger binding of drivers to interfaces. probe() | 1462 | * We could use a GetInterface call, but if a device is |
1456 | * routines may install different altsettings and may | 1463 | * so non-compliant that it doesn't have altsetting 0 |
1457 | * claim() any interfaces not yet bound. Many class drivers | 1464 | * then I wouldn't trust its reply anyway. |
1458 | * need that: CDC, audio, video, etc. | ||
1459 | */ | 1465 | */ |
1460 | for (i = 0; i < nintf; ++i) { | 1466 | if (!alt) |
1461 | struct usb_interface *intf = cp->interface[i]; | 1467 | alt = &intf->altsetting[0]; |
1462 | 1468 | ||
1463 | dev_dbg (&dev->dev, | 1469 | intf->cur_altsetting = alt; |
1464 | "adding %s (config #%d, interface %d)\n", | 1470 | usb_enable_interface(dev, intf); |
1465 | intf->dev.bus_id, configuration, | 1471 | intf->dev.parent = &dev->dev; |
1466 | intf->cur_altsetting->desc.bInterfaceNumber); | 1472 | intf->dev.driver = NULL; |
1467 | ret = device_add (&intf->dev); | 1473 | intf->dev.bus = &usb_bus_type; |
1468 | if (ret != 0) { | 1474 | intf->dev.dma_mask = dev->dev.dma_mask; |
1469 | dev_err(&dev->dev, | 1475 | intf->dev.release = release_interface; |
1470 | "device_add(%s) --> %d\n", | 1476 | device_initialize (&intf->dev); |
1471 | intf->dev.bus_id, | 1477 | mark_quiesced(intf); |
1472 | ret); | 1478 | sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", |
1473 | continue; | 1479 | dev->bus->busnum, dev->devpath, |
1474 | } | 1480 | configuration, alt->desc.bInterfaceNumber); |
1475 | usb_create_sysfs_intf_files (intf); | 1481 | } |
1482 | kfree(new_interfaces); | ||
1483 | |||
1484 | if (cp->string == NULL) | ||
1485 | cp->string = usb_cache_string(dev, cp->desc.iConfiguration); | ||
1486 | |||
1487 | /* Now that all the interfaces are set up, register them | ||
1488 | * to trigger binding of drivers to interfaces. probe() | ||
1489 | * routines may install different altsettings and may | ||
1490 | * claim() any interfaces not yet bound. Many class drivers | ||
1491 | * need that: CDC, audio, video, etc. | ||
1492 | */ | ||
1493 | for (i = 0; i < nintf; ++i) { | ||
1494 | struct usb_interface *intf = cp->interface[i]; | ||
1495 | |||
1496 | dev_dbg (&dev->dev, | ||
1497 | "adding %s (config #%d, interface %d)\n", | ||
1498 | intf->dev.bus_id, configuration, | ||
1499 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
1500 | ret = device_add (&intf->dev); | ||
1501 | if (ret != 0) { | ||
1502 | dev_err(&dev->dev, "device_add(%s) --> %d\n", | ||
1503 | intf->dev.bus_id, ret); | ||
1504 | continue; | ||
1476 | } | 1505 | } |
1506 | usb_create_sysfs_intf_files (intf); | ||
1477 | } | 1507 | } |
1478 | 1508 | ||
1479 | return 0; | 1509 | return 0; |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 71d881327e88..3f49bf51cff7 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -15,203 +15,6 @@ | |||
15 | #include <linux/usb.h> | 15 | #include <linux/usb.h> |
16 | #include "usb.h" | 16 | #include "usb.h" |
17 | 17 | ||
18 | /* endpoint stuff */ | ||
19 | struct ep_object { | ||
20 | struct usb_endpoint_descriptor *desc; | ||
21 | struct usb_device *udev; | ||
22 | struct kobject kobj; | ||
23 | }; | ||
24 | #define to_ep_object(_kobj) \ | ||
25 | container_of(_kobj, struct ep_object, kobj) | ||
26 | |||
27 | struct ep_attribute { | ||
28 | struct attribute attr; | ||
29 | ssize_t (*show)(struct usb_device *, | ||
30 | struct usb_endpoint_descriptor *, char *); | ||
31 | }; | ||
32 | #define to_ep_attribute(_attr) \ | ||
33 | container_of(_attr, struct ep_attribute, attr) | ||
34 | |||
35 | #define EP_ATTR(_name) \ | ||
36 | struct ep_attribute ep_##_name = { \ | ||
37 | .attr = {.name = #_name, .owner = THIS_MODULE, \ | ||
38 | .mode = S_IRUGO}, \ | ||
39 | .show = show_ep_##_name} | ||
40 | |||
41 | #define usb_ep_attr(field, format_string) \ | ||
42 | static ssize_t show_ep_##field(struct usb_device *udev, \ | ||
43 | struct usb_endpoint_descriptor *desc, \ | ||
44 | char *buf) \ | ||
45 | { \ | ||
46 | return sprintf(buf, format_string, desc->field); \ | ||
47 | } \ | ||
48 | static EP_ATTR(field); | ||
49 | |||
50 | usb_ep_attr(bLength, "%02x\n") | ||
51 | usb_ep_attr(bEndpointAddress, "%02x\n") | ||
52 | usb_ep_attr(bmAttributes, "%02x\n") | ||
53 | usb_ep_attr(bInterval, "%02x\n") | ||
54 | |||
55 | static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev, | ||
56 | struct usb_endpoint_descriptor *desc, char *buf) | ||
57 | { | ||
58 | return sprintf(buf, "%04x\n", | ||
59 | le16_to_cpu(desc->wMaxPacketSize) & 0x07ff); | ||
60 | } | ||
61 | static EP_ATTR(wMaxPacketSize); | ||
62 | |||
63 | static ssize_t show_ep_type(struct usb_device *udev, | ||
64 | struct usb_endpoint_descriptor *desc, char *buf) | ||
65 | { | ||
66 | char *type = "unknown"; | ||
67 | |||
68 | switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | ||
69 | case USB_ENDPOINT_XFER_CONTROL: | ||
70 | type = "Control"; | ||
71 | break; | ||
72 | case USB_ENDPOINT_XFER_ISOC: | ||
73 | type = "Isoc"; | ||
74 | break; | ||
75 | case USB_ENDPOINT_XFER_BULK: | ||
76 | type = "Bulk"; | ||
77 | break; | ||
78 | case USB_ENDPOINT_XFER_INT: | ||
79 | type = "Interrupt"; | ||
80 | break; | ||
81 | } | ||
82 | return sprintf(buf, "%s\n", type); | ||
83 | } | ||
84 | static EP_ATTR(type); | ||
85 | |||
86 | static ssize_t show_ep_interval(struct usb_device *udev, | ||
87 | struct usb_endpoint_descriptor *desc, char *buf) | ||
88 | { | ||
89 | char unit; | ||
90 | unsigned interval = 0; | ||
91 | unsigned in; | ||
92 | |||
93 | in = (desc->bEndpointAddress & USB_DIR_IN); | ||
94 | |||
95 | switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | ||
96 | case USB_ENDPOINT_XFER_CONTROL: | ||
97 | if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ | ||
98 | interval = desc->bInterval; | ||
99 | break; | ||
100 | case USB_ENDPOINT_XFER_ISOC: | ||
101 | interval = 1 << (desc->bInterval - 1); | ||
102 | break; | ||
103 | case USB_ENDPOINT_XFER_BULK: | ||
104 | if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ | ||
105 | interval = desc->bInterval; | ||
106 | break; | ||
107 | case USB_ENDPOINT_XFER_INT: | ||
108 | if (udev->speed == USB_SPEED_HIGH) | ||
109 | interval = 1 << (desc->bInterval - 1); | ||
110 | else | ||
111 | interval = desc->bInterval; | ||
112 | break; | ||
113 | } | ||
114 | interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000; | ||
115 | if (interval % 1000) | ||
116 | unit = 'u'; | ||
117 | else { | ||
118 | unit = 'm'; | ||
119 | interval /= 1000; | ||
120 | } | ||
121 | |||
122 | return sprintf(buf, "%d%cs\n", interval, unit); | ||
123 | } | ||
124 | static EP_ATTR(interval); | ||
125 | |||
126 | static ssize_t show_ep_direction(struct usb_device *udev, | ||
127 | struct usb_endpoint_descriptor *desc, char *buf) | ||
128 | { | ||
129 | char *direction; | ||
130 | |||
131 | if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
132 | USB_ENDPOINT_XFER_CONTROL) | ||
133 | direction = "both"; | ||
134 | else if (desc->bEndpointAddress & USB_DIR_IN) | ||
135 | direction = "in"; | ||
136 | else | ||
137 | direction = "out"; | ||
138 | return sprintf(buf, "%s\n", direction); | ||
139 | } | ||
140 | static EP_ATTR(direction); | ||
141 | |||
142 | static struct attribute *ep_attrs[] = { | ||
143 | &ep_bLength.attr, | ||
144 | &ep_bEndpointAddress.attr, | ||
145 | &ep_bmAttributes.attr, | ||
146 | &ep_bInterval.attr, | ||
147 | &ep_wMaxPacketSize.attr, | ||
148 | &ep_type.attr, | ||
149 | &ep_interval.attr, | ||
150 | &ep_direction.attr, | ||
151 | NULL, | ||
152 | }; | ||
153 | |||
154 | static void ep_object_release(struct kobject *kobj) | ||
155 | { | ||
156 | kfree(to_ep_object(kobj)); | ||
157 | } | ||
158 | |||
159 | static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr, | ||
160 | char *buf) | ||
161 | { | ||
162 | struct ep_object *ep_obj = to_ep_object(kobj); | ||
163 | struct ep_attribute *ep_attr = to_ep_attribute(attr); | ||
164 | |||
165 | return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf); | ||
166 | } | ||
167 | |||
168 | static struct sysfs_ops ep_object_sysfs_ops = { | ||
169 | .show = ep_object_show, | ||
170 | }; | ||
171 | |||
172 | static struct kobj_type ep_object_ktype = { | ||
173 | .release = ep_object_release, | ||
174 | .sysfs_ops = &ep_object_sysfs_ops, | ||
175 | .default_attrs = ep_attrs, | ||
176 | }; | ||
177 | |||
178 | static void usb_create_ep_files(struct kobject *parent, | ||
179 | struct usb_host_endpoint *endpoint, | ||
180 | struct usb_device *udev) | ||
181 | { | ||
182 | struct ep_object *ep_obj; | ||
183 | struct kobject *kobj; | ||
184 | |||
185 | ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL); | ||
186 | if (!ep_obj) | ||
187 | return; | ||
188 | |||
189 | ep_obj->desc = &endpoint->desc; | ||
190 | ep_obj->udev = udev; | ||
191 | |||
192 | kobj = &ep_obj->kobj; | ||
193 | kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress); | ||
194 | kobj->parent = parent; | ||
195 | kobj->ktype = &ep_object_ktype; | ||
196 | |||
197 | /* Don't use kobject_register, because it generates a hotplug event */ | ||
198 | kobject_init(kobj); | ||
199 | if (kobject_add(kobj) == 0) | ||
200 | endpoint->kobj = kobj; | ||
201 | else | ||
202 | kobject_put(kobj); | ||
203 | } | ||
204 | |||
205 | static void usb_remove_ep_files(struct usb_host_endpoint *endpoint) | ||
206 | { | ||
207 | |||
208 | if (endpoint->kobj) { | ||
209 | kobject_del(endpoint->kobj); | ||
210 | kobject_put(endpoint->kobj); | ||
211 | endpoint->kobj = NULL; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | /* Active configuration fields */ | 18 | /* Active configuration fields */ |
216 | #define usb_actconfig_show(field, multiplier, format_string) \ | 19 | #define usb_actconfig_show(field, multiplier, format_string) \ |
217 | static ssize_t show_##field (struct device *dev, \ | 20 | static ssize_t show_##field (struct device *dev, \ |
@@ -420,7 +223,7 @@ void usb_create_sysfs_dev_files (struct usb_device *udev) | |||
420 | if (udev->serial) | 223 | if (udev->serial) |
421 | device_create_file (dev, &dev_attr_serial); | 224 | device_create_file (dev, &dev_attr_serial); |
422 | device_create_file (dev, &dev_attr_configuration); | 225 | device_create_file (dev, &dev_attr_configuration); |
423 | usb_create_ep_files(&dev->kobj, &udev->ep0, udev); | 226 | usb_create_ep_files(dev, &udev->ep0, udev); |
424 | } | 227 | } |
425 | 228 | ||
426 | void usb_remove_sysfs_dev_files (struct usb_device *udev) | 229 | void usb_remove_sysfs_dev_files (struct usb_device *udev) |
@@ -524,7 +327,7 @@ static inline void usb_create_intf_ep_files(struct usb_interface *intf, | |||
524 | 327 | ||
525 | iface_desc = intf->cur_altsetting; | 328 | iface_desc = intf->cur_altsetting; |
526 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) | 329 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) |
527 | usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i], | 330 | usb_create_ep_files(&intf->dev, &iface_desc->endpoint[i], |
528 | udev); | 331 | udev); |
529 | } | 332 | } |
530 | 333 | ||
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b7fdc1cd134a..fb488c8a860c 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -991,6 +991,8 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, | |||
991 | 991 | ||
992 | static int verify_suspended(struct device *dev, void *unused) | 992 | static int verify_suspended(struct device *dev, void *unused) |
993 | { | 993 | { |
994 | if (dev->driver == NULL) | ||
995 | return 0; | ||
994 | return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; | 996 | return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; |
995 | } | 997 | } |
996 | 998 | ||
@@ -1207,6 +1209,7 @@ EXPORT_SYMBOL(usb_ifnum_to_if); | |||
1207 | EXPORT_SYMBOL(usb_altnum_to_altsetting); | 1209 | EXPORT_SYMBOL(usb_altnum_to_altsetting); |
1208 | 1210 | ||
1209 | EXPORT_SYMBOL(usb_reset_device); | 1211 | EXPORT_SYMBOL(usb_reset_device); |
1212 | EXPORT_SYMBOL(usb_reset_composite_device); | ||
1210 | 1213 | ||
1211 | EXPORT_SYMBOL(__usb_get_extra_descriptor); | 1214 | EXPORT_SYMBOL(__usb_get_extra_descriptor); |
1212 | 1215 | ||
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 4647e1ebc68d..7a650c763a62 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -4,6 +4,9 @@ extern void usb_create_sysfs_dev_files (struct usb_device *dev); | |||
4 | extern void usb_remove_sysfs_dev_files (struct usb_device *dev); | 4 | extern void usb_remove_sysfs_dev_files (struct usb_device *dev); |
5 | extern void usb_create_sysfs_intf_files (struct usb_interface *intf); | 5 | extern void usb_create_sysfs_intf_files (struct usb_interface *intf); |
6 | extern void usb_remove_sysfs_intf_files (struct usb_interface *intf); | 6 | extern void usb_remove_sysfs_intf_files (struct usb_interface *intf); |
7 | extern void usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint, | ||
8 | struct usb_device *udev); | ||
9 | extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint); | ||
7 | 10 | ||
8 | extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr); | 11 | extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr); |
9 | extern void usb_disable_interface (struct usb_device *dev, | 12 | extern void usb_disable_interface (struct usb_device *dev, |
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 9c4422ac9de4..078daa026718 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #include <asm/unaligned.h> | 49 | #include <asm/unaligned.h> |
50 | 50 | ||
51 | #include <linux/usb_ch9.h> | 51 | #include <linux/usb_ch9.h> |
52 | #include <linux/usb_cdc.h> | 52 | #include <linux/usb/cdc.h> |
53 | #include <linux/usb_gadget.h> | 53 | #include <linux/usb_gadget.h> |
54 | 54 | ||
55 | #include <linux/random.h> | 55 | #include <linux/random.h> |
@@ -101,9 +101,9 @@ static const char driver_desc [] = DRIVER_DESC; | |||
101 | 101 | ||
102 | /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ | 102 | /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ |
103 | #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ | 103 | #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ |
104 | |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ | 104 | |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ |
105 | |USB_CDC_PACKET_TYPE_PROMISCUOUS \ | 105 | |USB_CDC_PACKET_TYPE_PROMISCUOUS \ |
106 | |USB_CDC_PACKET_TYPE_DIRECTED) | 106 | |USB_CDC_PACKET_TYPE_DIRECTED) |
107 | 107 | ||
108 | 108 | ||
109 | /*-------------------------------------------------------------------------*/ | 109 | /*-------------------------------------------------------------------------*/ |
@@ -318,7 +318,7 @@ static inline int rndis_active(struct eth_dev *dev) | |||
318 | #define DEFAULT_QLEN 2 /* double buffering by default */ | 318 | #define DEFAULT_QLEN 2 /* double buffering by default */ |
319 | 319 | ||
320 | /* peak bulk transfer bits-per-second */ | 320 | /* peak bulk transfer bits-per-second */ |
321 | #define HS_BPS (13 * 512 * 8 * 1000 * 8) | 321 | #define HS_BPS (13 * 512 * 8 * 1000 * 8) |
322 | #define FS_BPS (19 * 64 * 1 * 1000 * 8) | 322 | #define FS_BPS (19 * 64 * 1 * 1000 * 8) |
323 | 323 | ||
324 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 324 | #ifdef CONFIG_USB_GADGET_DUALSPEED |
@@ -466,7 +466,7 @@ eth_config = { | |||
466 | }; | 466 | }; |
467 | 467 | ||
468 | #ifdef CONFIG_USB_ETH_RNDIS | 468 | #ifdef CONFIG_USB_ETH_RNDIS |
469 | static struct usb_config_descriptor | 469 | static struct usb_config_descriptor |
470 | rndis_config = { | 470 | rndis_config = { |
471 | .bLength = sizeof rndis_config, | 471 | .bLength = sizeof rndis_config, |
472 | .bDescriptorType = USB_DT_CONFIG, | 472 | .bDescriptorType = USB_DT_CONFIG, |
@@ -511,7 +511,7 @@ static const struct usb_interface_descriptor | |||
511 | rndis_control_intf = { | 511 | rndis_control_intf = { |
512 | .bLength = sizeof rndis_control_intf, | 512 | .bLength = sizeof rndis_control_intf, |
513 | .bDescriptorType = USB_DT_INTERFACE, | 513 | .bDescriptorType = USB_DT_INTERFACE, |
514 | 514 | ||
515 | .bInterfaceNumber = 0, | 515 | .bInterfaceNumber = 0, |
516 | .bNumEndpoints = 1, | 516 | .bNumEndpoints = 1, |
517 | .bInterfaceClass = USB_CLASS_COMM, | 517 | .bInterfaceClass = USB_CLASS_COMM, |
@@ -545,20 +545,20 @@ static const struct usb_cdc_union_desc union_desc = { | |||
545 | #ifdef CONFIG_USB_ETH_RNDIS | 545 | #ifdef CONFIG_USB_ETH_RNDIS |
546 | 546 | ||
547 | static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = { | 547 | static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = { |
548 | .bLength = sizeof call_mgmt_descriptor, | 548 | .bLength = sizeof call_mgmt_descriptor, |
549 | .bDescriptorType = USB_DT_CS_INTERFACE, | 549 | .bDescriptorType = USB_DT_CS_INTERFACE, |
550 | .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, | 550 | .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, |
551 | 551 | ||
552 | .bmCapabilities = 0x00, | 552 | .bmCapabilities = 0x00, |
553 | .bDataInterface = 0x01, | 553 | .bDataInterface = 0x01, |
554 | }; | 554 | }; |
555 | 555 | ||
556 | static const struct usb_cdc_acm_descriptor acm_descriptor = { | 556 | static const struct usb_cdc_acm_descriptor acm_descriptor = { |
557 | .bLength = sizeof acm_descriptor, | 557 | .bLength = sizeof acm_descriptor, |
558 | .bDescriptorType = USB_DT_CS_INTERFACE, | 558 | .bDescriptorType = USB_DT_CS_INTERFACE, |
559 | .bDescriptorSubType = USB_CDC_ACM_TYPE, | 559 | .bDescriptorSubType = USB_CDC_ACM_TYPE, |
560 | 560 | ||
561 | .bmCapabilities = 0x00, | 561 | .bmCapabilities = 0x00, |
562 | }; | 562 | }; |
563 | 563 | ||
564 | #endif | 564 | #endif |
@@ -595,7 +595,7 @@ static const struct usb_cdc_ether_desc ether_desc = { | |||
595 | * RNDIS requires the status endpoint, since it uses that encapsulation | 595 | * RNDIS requires the status endpoint, since it uses that encapsulation |
596 | * mechanism for its funky RPC scheme. | 596 | * mechanism for its funky RPC scheme. |
597 | */ | 597 | */ |
598 | 598 | ||
599 | #define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ | 599 | #define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ |
600 | #define STATUS_BYTECOUNT 16 /* 8 byte header + data */ | 600 | #define STATUS_BYTECOUNT 16 /* 8 byte header + data */ |
601 | 601 | ||
@@ -978,7 +978,7 @@ set_ether_config (struct eth_dev *dev, gfp_t gfp_flags) | |||
978 | 978 | ||
979 | result = usb_ep_enable (dev->status_ep, dev->status); | 979 | result = usb_ep_enable (dev->status_ep, dev->status); |
980 | if (result != 0) { | 980 | if (result != 0) { |
981 | DEBUG (dev, "enable %s --> %d\n", | 981 | DEBUG (dev, "enable %s --> %d\n", |
982 | dev->status_ep->name, result); | 982 | dev->status_ep->name, result); |
983 | goto done; | 983 | goto done; |
984 | } | 984 | } |
@@ -1002,15 +1002,15 @@ set_ether_config (struct eth_dev *dev, gfp_t gfp_flags) | |||
1002 | if (!cdc_active(dev)) { | 1002 | if (!cdc_active(dev)) { |
1003 | result = usb_ep_enable (dev->in_ep, dev->in); | 1003 | result = usb_ep_enable (dev->in_ep, dev->in); |
1004 | if (result != 0) { | 1004 | if (result != 0) { |
1005 | DEBUG(dev, "enable %s --> %d\n", | 1005 | DEBUG(dev, "enable %s --> %d\n", |
1006 | dev->in_ep->name, result); | 1006 | dev->in_ep->name, result); |
1007 | goto done; | 1007 | goto done; |
1008 | } | 1008 | } |
1009 | 1009 | ||
1010 | result = usb_ep_enable (dev->out_ep, dev->out); | 1010 | result = usb_ep_enable (dev->out_ep, dev->out); |
1011 | if (result != 0) { | 1011 | if (result != 0) { |
1012 | DEBUG (dev, "enable %s --> %d\n", | 1012 | DEBUG (dev, "enable %s --> %d\n", |
1013 | dev->in_ep->name, result); | 1013 | dev->out_ep->name, result); |
1014 | goto done; | 1014 | goto done; |
1015 | } | 1015 | } |
1016 | } | 1016 | } |
@@ -1144,7 +1144,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags) | |||
1144 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1144 | #ifdef CONFIG_USB_GADGET_DUALSPEED |
1145 | case USB_SPEED_HIGH: speed = "high"; break; | 1145 | case USB_SPEED_HIGH: speed = "high"; break; |
1146 | #endif | 1146 | #endif |
1147 | default: speed = "?"; break; | 1147 | default: speed = "?"; break; |
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | dev->config = number; | 1150 | dev->config = number; |
@@ -1206,7 +1206,7 @@ static void issue_start_status (struct eth_dev *dev) | |||
1206 | struct usb_request *req = dev->stat_req; | 1206 | struct usb_request *req = dev->stat_req; |
1207 | struct usb_cdc_notification *event; | 1207 | struct usb_cdc_notification *event; |
1208 | int value; | 1208 | int value; |
1209 | 1209 | ||
1210 | DEBUG (dev, "%s, flush old status first\n", __FUNCTION__); | 1210 | DEBUG (dev, "%s, flush old status first\n", __FUNCTION__); |
1211 | 1211 | ||
1212 | /* flush old status | 1212 | /* flush old status |
@@ -1268,7 +1268,7 @@ static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req) | |||
1268 | { | 1268 | { |
1269 | struct eth_dev *dev = ep->driver_data; | 1269 | struct eth_dev *dev = ep->driver_data; |
1270 | int status; | 1270 | int status; |
1271 | 1271 | ||
1272 | /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ | 1272 | /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ |
1273 | spin_lock(&dev->lock); | 1273 | spin_lock(&dev->lock); |
1274 | status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf); | 1274 | status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf); |
@@ -1472,7 +1472,7 @@ done_set_intf: | |||
1472 | 1472 | ||
1473 | #endif /* DEV_CONFIG_CDC */ | 1473 | #endif /* DEV_CONFIG_CDC */ |
1474 | 1474 | ||
1475 | #ifdef CONFIG_USB_ETH_RNDIS | 1475 | #ifdef CONFIG_USB_ETH_RNDIS |
1476 | /* RNDIS uses the CDC command encapsulation mechanism to implement | 1476 | /* RNDIS uses the CDC command encapsulation mechanism to implement |
1477 | * an RPC scheme, with much getting/setting of attributes by OID. | 1477 | * an RPC scheme, with much getting/setting of attributes by OID. |
1478 | */ | 1478 | */ |
@@ -1489,7 +1489,7 @@ done_set_intf: | |||
1489 | req->complete = rndis_command_complete; | 1489 | req->complete = rndis_command_complete; |
1490 | /* later, rndis_control_ack () sends a notification */ | 1490 | /* later, rndis_control_ack () sends a notification */ |
1491 | break; | 1491 | break; |
1492 | 1492 | ||
1493 | case USB_CDC_GET_ENCAPSULATED_RESPONSE: | 1493 | case USB_CDC_GET_ENCAPSULATED_RESPONSE: |
1494 | if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE) | 1494 | if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE) |
1495 | == ctrl->bRequestType | 1495 | == ctrl->bRequestType |
@@ -1641,7 +1641,7 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) | |||
1641 | DEBUG (dev, "no rx skb\n"); | 1641 | DEBUG (dev, "no rx skb\n"); |
1642 | goto enomem; | 1642 | goto enomem; |
1643 | } | 1643 | } |
1644 | 1644 | ||
1645 | /* Some platforms perform better when IP packets are aligned, | 1645 | /* Some platforms perform better when IP packets are aligned, |
1646 | * but on at least one, checksumming fails otherwise. Note: | 1646 | * but on at least one, checksumming fails otherwise. Note: |
1647 | * RNDIS headers involve variable numbers of LE32 values. | 1647 | * RNDIS headers involve variable numbers of LE32 values. |
@@ -1720,7 +1720,7 @@ quiesce: | |||
1720 | case -EOVERFLOW: | 1720 | case -EOVERFLOW: |
1721 | dev->stats.rx_over_errors++; | 1721 | dev->stats.rx_over_errors++; |
1722 | // FALLTHROUGH | 1722 | // FALLTHROUGH |
1723 | 1723 | ||
1724 | default: | 1724 | default: |
1725 | dev->stats.rx_errors++; | 1725 | dev->stats.rx_errors++; |
1726 | DEBUG (dev, "rx status %d\n", status); | 1726 | DEBUG (dev, "rx status %d\n", status); |
@@ -1915,7 +1915,7 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) | |||
1915 | sizeof (struct rndis_packet_msg_type)); | 1915 | sizeof (struct rndis_packet_msg_type)); |
1916 | if (!skb_rndis) | 1916 | if (!skb_rndis) |
1917 | goto drop; | 1917 | goto drop; |
1918 | 1918 | ||
1919 | dev_kfree_skb_any (skb); | 1919 | dev_kfree_skb_any (skb); |
1920 | skb = skb_rndis; | 1920 | skb = skb_rndis; |
1921 | rndis_add_hdr (skb); | 1921 | rndis_add_hdr (skb); |
@@ -2001,7 +2001,7 @@ static int rndis_control_ack (struct net_device *net) | |||
2001 | struct eth_dev *dev = netdev_priv(net); | 2001 | struct eth_dev *dev = netdev_priv(net); |
2002 | u32 length; | 2002 | u32 length; |
2003 | struct usb_request *resp = dev->stat_req; | 2003 | struct usb_request *resp = dev->stat_req; |
2004 | 2004 | ||
2005 | /* in case RNDIS calls this after disconnect */ | 2005 | /* in case RNDIS calls this after disconnect */ |
2006 | if (!dev->status) { | 2006 | if (!dev->status) { |
2007 | DEBUG (dev, "status ENODEV\n"); | 2007 | DEBUG (dev, "status ENODEV\n"); |
@@ -2021,16 +2021,16 @@ static int rndis_control_ack (struct net_device *net) | |||
2021 | resp->length = 8; | 2021 | resp->length = 8; |
2022 | resp->complete = rndis_control_ack_complete; | 2022 | resp->complete = rndis_control_ack_complete; |
2023 | resp->context = dev; | 2023 | resp->context = dev; |
2024 | 2024 | ||
2025 | *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1); | 2025 | *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1); |
2026 | *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); | 2026 | *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); |
2027 | 2027 | ||
2028 | length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC); | 2028 | length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC); |
2029 | if (length < 0) { | 2029 | if (length < 0) { |
2030 | resp->status = 0; | 2030 | resp->status = 0; |
2031 | rndis_control_ack_complete (dev->status_ep, resp); | 2031 | rndis_control_ack_complete (dev->status_ep, resp); |
2032 | } | 2032 | } |
2033 | 2033 | ||
2034 | return 0; | 2034 | return 0; |
2035 | } | 2035 | } |
2036 | 2036 | ||
@@ -2047,7 +2047,7 @@ static void eth_start (struct eth_dev *dev, gfp_t gfp_flags) | |||
2047 | /* fill the rx queue */ | 2047 | /* fill the rx queue */ |
2048 | rx_fill (dev, gfp_flags); | 2048 | rx_fill (dev, gfp_flags); |
2049 | 2049 | ||
2050 | /* and open the tx floodgates */ | 2050 | /* and open the tx floodgates */ |
2051 | atomic_set (&dev->tx_qlen, 0); | 2051 | atomic_set (&dev->tx_qlen, 0); |
2052 | netif_wake_queue (dev->net); | 2052 | netif_wake_queue (dev->net); |
2053 | if (rndis_active(dev)) { | 2053 | if (rndis_active(dev)) { |
@@ -2076,7 +2076,7 @@ static int eth_stop (struct net_device *net) | |||
2076 | netif_stop_queue (net); | 2076 | netif_stop_queue (net); |
2077 | 2077 | ||
2078 | DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", | 2078 | DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", |
2079 | dev->stats.rx_packets, dev->stats.tx_packets, | 2079 | dev->stats.rx_packets, dev->stats.tx_packets, |
2080 | dev->stats.rx_errors, dev->stats.tx_errors | 2080 | dev->stats.rx_errors, dev->stats.tx_errors |
2081 | ); | 2081 | ); |
2082 | 2082 | ||
@@ -2095,7 +2095,7 @@ static int eth_stop (struct net_device *net) | |||
2095 | usb_ep_enable (dev->status_ep, dev->status); | 2095 | usb_ep_enable (dev->status_ep, dev->status); |
2096 | } | 2096 | } |
2097 | } | 2097 | } |
2098 | 2098 | ||
2099 | if (rndis_active(dev)) { | 2099 | if (rndis_active(dev)) { |
2100 | rndis_set_param_medium (dev->rndis_config, | 2100 | rndis_set_param_medium (dev->rndis_config, |
2101 | NDIS_MEDIUM_802_3, 0); | 2101 | NDIS_MEDIUM_802_3, 0); |
@@ -2301,7 +2301,7 @@ autoconf_fail: | |||
2301 | return -ENODEV; | 2301 | return -ENODEV; |
2302 | } | 2302 | } |
2303 | in_ep->driver_data = in_ep; /* claim */ | 2303 | in_ep->driver_data = in_ep; /* claim */ |
2304 | 2304 | ||
2305 | out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc); | 2305 | out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc); |
2306 | if (!out_ep) | 2306 | if (!out_ep) |
2307 | goto autoconf_fail; | 2307 | goto autoconf_fail; |
@@ -2374,8 +2374,8 @@ autoconf_fail: | |||
2374 | #endif | 2374 | #endif |
2375 | } | 2375 | } |
2376 | 2376 | ||
2377 | net = alloc_etherdev (sizeof *dev); | 2377 | net = alloc_etherdev (sizeof *dev); |
2378 | if (!net) | 2378 | if (!net) |
2379 | return status; | 2379 | return status; |
2380 | dev = netdev_priv(net); | 2380 | dev = netdev_priv(net); |
2381 | spin_lock_init (&dev->lock); | 2381 | spin_lock_init (&dev->lock); |
@@ -2454,7 +2454,7 @@ autoconf_fail: | |||
2454 | dev->gadget = gadget; | 2454 | dev->gadget = gadget; |
2455 | set_gadget_data (gadget, dev); | 2455 | set_gadget_data (gadget, dev); |
2456 | gadget->ep0->driver_data = dev; | 2456 | gadget->ep0->driver_data = dev; |
2457 | 2457 | ||
2458 | /* two kinds of host-initiated state changes: | 2458 | /* two kinds of host-initiated state changes: |
2459 | * - iff DATA transfer is active, carrier is "on" | 2459 | * - iff DATA transfer is active, carrier is "on" |
2460 | * - tx queueing enabled if open *and* carrier is "on" | 2460 | * - tx queueing enabled if open *and* carrier is "on" |
@@ -2462,8 +2462,8 @@ autoconf_fail: | |||
2462 | netif_stop_queue (dev->net); | 2462 | netif_stop_queue (dev->net); |
2463 | netif_carrier_off (dev->net); | 2463 | netif_carrier_off (dev->net); |
2464 | 2464 | ||
2465 | SET_NETDEV_DEV (dev->net, &gadget->dev); | 2465 | SET_NETDEV_DEV (dev->net, &gadget->dev); |
2466 | status = register_netdev (dev->net); | 2466 | status = register_netdev (dev->net); |
2467 | if (status < 0) | 2467 | if (status < 0) |
2468 | goto fail1; | 2468 | goto fail1; |
2469 | 2469 | ||
@@ -2488,7 +2488,7 @@ autoconf_fail: | |||
2488 | u32 vendorID = 0; | 2488 | u32 vendorID = 0; |
2489 | 2489 | ||
2490 | /* FIXME RNDIS vendor id == "vendor NIC code" == ? */ | 2490 | /* FIXME RNDIS vendor id == "vendor NIC code" == ? */ |
2491 | 2491 | ||
2492 | dev->rndis_config = rndis_register (rndis_control_ack); | 2492 | dev->rndis_config = rndis_register (rndis_control_ack); |
2493 | if (dev->rndis_config < 0) { | 2493 | if (dev->rndis_config < 0) { |
2494 | fail0: | 2494 | fail0: |
@@ -2496,7 +2496,7 @@ fail0: | |||
2496 | status = -ENODEV; | 2496 | status = -ENODEV; |
2497 | goto fail; | 2497 | goto fail; |
2498 | } | 2498 | } |
2499 | 2499 | ||
2500 | /* these set up a lot of the OIDs that RNDIS needs */ | 2500 | /* these set up a lot of the OIDs that RNDIS needs */ |
2501 | rndis_set_host_mac (dev->rndis_config, dev->host_mac); | 2501 | rndis_set_host_mac (dev->rndis_config, dev->host_mac); |
2502 | if (rndis_set_param_dev (dev->rndis_config, dev->net, | 2502 | if (rndis_set_param_dev (dev->rndis_config, dev->net, |
@@ -2556,7 +2556,7 @@ static struct usb_gadget_driver eth_driver = { | |||
2556 | .suspend = eth_suspend, | 2556 | .suspend = eth_suspend, |
2557 | .resume = eth_resume, | 2557 | .resume = eth_resume, |
2558 | 2558 | ||
2559 | .driver = { | 2559 | .driver = { |
2560 | .name = (char *) shortname, | 2560 | .name = (char *) shortname, |
2561 | .owner = THIS_MODULE, | 2561 | .owner = THIS_MODULE, |
2562 | }, | 2562 | }, |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 6f887478b148..a43dc908ac59 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -1906,7 +1906,6 @@ static int fsync_sub(struct lun *curlun) | |||
1906 | 1906 | ||
1907 | inode = filp->f_dentry->d_inode; | 1907 | inode = filp->f_dentry->d_inode; |
1908 | mutex_lock(&inode->i_mutex); | 1908 | mutex_lock(&inode->i_mutex); |
1909 | current->flags |= PF_SYNCWRITE; | ||
1910 | rc = filemap_fdatawrite(inode->i_mapping); | 1909 | rc = filemap_fdatawrite(inode->i_mapping); |
1911 | err = filp->f_op->fsync(filp, filp->f_dentry, 1); | 1910 | err = filp->f_op->fsync(filp, filp->f_dentry, 1); |
1912 | if (!rc) | 1911 | if (!rc) |
@@ -1914,7 +1913,6 @@ static int fsync_sub(struct lun *curlun) | |||
1914 | err = filemap_fdatawait(inode->i_mapping); | 1913 | err = filemap_fdatawait(inode->i_mapping); |
1915 | if (!rc) | 1914 | if (!rc) |
1916 | rc = err; | 1915 | rc = err; |
1917 | current->flags &= ~PF_SYNCWRITE; | ||
1918 | mutex_unlock(&inode->i_mutex); | 1916 | mutex_unlock(&inode->i_mutex); |
1919 | VLDBG(curlun, "fdatasync -> %d\n", rc); | 1917 | VLDBG(curlun, "fdatasync -> %d\n", rc); |
1920 | return rc; | 1918 | return rc; |
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 66b81bbf6bee..5378c1757292 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
@@ -1850,7 +1850,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1850 | unsigned long resource, len; | 1850 | unsigned long resource, len; |
1851 | void __iomem *base = NULL; | 1851 | void __iomem *base = NULL; |
1852 | int retval; | 1852 | int retval; |
1853 | char buf [8], *bufp; | ||
1854 | 1853 | ||
1855 | /* if you want to support more than one controller in a system, | 1854 | /* if you want to support more than one controller in a system, |
1856 | * usb_gadget_driver_{register,unregister}() must change. | 1855 | * usb_gadget_driver_{register,unregister}() must change. |
@@ -1913,20 +1912,14 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1913 | pci_set_drvdata(pdev, dev); | 1912 | pci_set_drvdata(pdev, dev); |
1914 | INFO(dev, "%s\n", driver_desc); | 1913 | INFO(dev, "%s\n", driver_desc); |
1915 | INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr()); | 1914 | INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr()); |
1916 | #ifndef __sparc__ | 1915 | INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base); |
1917 | scnprintf(buf, sizeof buf, "%d", pdev->irq); | ||
1918 | bufp = buf; | ||
1919 | #else | ||
1920 | bufp = __irq_itoa(pdev->irq); | ||
1921 | #endif | ||
1922 | INFO(dev, "irq %s, pci mem %p\n", bufp, base); | ||
1923 | 1916 | ||
1924 | /* init to known state, then setup irqs */ | 1917 | /* init to known state, then setup irqs */ |
1925 | udc_reset(dev); | 1918 | udc_reset(dev); |
1926 | udc_reinit (dev); | 1919 | udc_reinit (dev); |
1927 | if (request_irq(pdev->irq, goku_irq, SA_SHIRQ/*|SA_SAMPLE_RANDOM*/, | 1920 | if (request_irq(pdev->irq, goku_irq, SA_SHIRQ/*|SA_SAMPLE_RANDOM*/, |
1928 | driver_name, dev) != 0) { | 1921 | driver_name, dev) != 0) { |
1929 | DBG(dev, "request interrupt %s failed\n", bufp); | 1922 | DBG(dev, "request interrupt %d failed\n", pdev->irq); |
1930 | retval = -EBUSY; | 1923 | retval = -EBUSY; |
1931 | goto done; | 1924 | goto done; |
1932 | } | 1925 | } |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 0eb010a3f5bc..3bdc5e3ba234 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -528,7 +528,7 @@ struct kiocb_priv { | |||
528 | struct usb_request *req; | 528 | struct usb_request *req; |
529 | struct ep_data *epdata; | 529 | struct ep_data *epdata; |
530 | void *buf; | 530 | void *buf; |
531 | char __user *ubuf; | 531 | char __user *ubuf; /* NULL for writes */ |
532 | unsigned actual; | 532 | unsigned actual; |
533 | }; | 533 | }; |
534 | 534 | ||
@@ -566,7 +566,6 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) | |||
566 | status = priv->actual; | 566 | status = priv->actual; |
567 | kfree(priv->buf); | 567 | kfree(priv->buf); |
568 | kfree(priv); | 568 | kfree(priv); |
569 | aio_put_req(iocb); | ||
570 | return status; | 569 | return status; |
571 | } | 570 | } |
572 | 571 | ||
@@ -580,8 +579,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) | |||
580 | spin_lock(&epdata->dev->lock); | 579 | spin_lock(&epdata->dev->lock); |
581 | priv->req = NULL; | 580 | priv->req = NULL; |
582 | priv->epdata = NULL; | 581 | priv->epdata = NULL; |
583 | if (NULL == iocb->ki_retry | 582 | if (priv->ubuf == NULL |
584 | || unlikely(0 == req->actual) | 583 | || unlikely(req->actual == 0) |
585 | || unlikely(kiocbIsCancelled(iocb))) { | 584 | || unlikely(kiocbIsCancelled(iocb))) { |
586 | kfree(req->buf); | 585 | kfree(req->buf); |
587 | kfree(priv); | 586 | kfree(priv); |
@@ -618,7 +617,7 @@ ep_aio_rwtail( | |||
618 | char __user *ubuf | 617 | char __user *ubuf |
619 | ) | 618 | ) |
620 | { | 619 | { |
621 | struct kiocb_priv *priv = (void *) &iocb->private; | 620 | struct kiocb_priv *priv; |
622 | struct usb_request *req; | 621 | struct usb_request *req; |
623 | ssize_t value; | 622 | ssize_t value; |
624 | 623 | ||
@@ -670,7 +669,7 @@ fail: | |||
670 | kfree(priv); | 669 | kfree(priv); |
671 | put_ep(epdata); | 670 | put_ep(epdata); |
672 | } else | 671 | } else |
673 | value = -EIOCBQUEUED; | 672 | value = (ubuf ? -EIOCBRETRY : -EIOCBQUEUED); |
674 | return value; | 673 | return value; |
675 | } | 674 | } |
676 | 675 | ||
@@ -1039,7 +1038,7 @@ scan: | |||
1039 | /* ep0 can't deliver events when STATE_SETUP */ | 1038 | /* ep0 can't deliver events when STATE_SETUP */ |
1040 | for (i = 0; i < n; i++) { | 1039 | for (i = 0; i < n; i++) { |
1041 | if (dev->event [i].type == GADGETFS_SETUP) { | 1040 | if (dev->event [i].type == GADGETFS_SETUP) { |
1042 | len = n = i + 1; | 1041 | len = i + 1; |
1043 | len *= sizeof (struct usb_gadgetfs_event); | 1042 | len *= sizeof (struct usb_gadgetfs_event); |
1044 | n = 0; | 1043 | n = 0; |
1045 | break; | 1044 | break; |
@@ -1587,13 +1586,13 @@ gadgetfs_create_file (struct super_block *sb, char const *name, | |||
1587 | static int activate_ep_files (struct dev_data *dev) | 1586 | static int activate_ep_files (struct dev_data *dev) |
1588 | { | 1587 | { |
1589 | struct usb_ep *ep; | 1588 | struct usb_ep *ep; |
1589 | struct ep_data *data; | ||
1590 | 1590 | ||
1591 | gadget_for_each_ep (ep, dev->gadget) { | 1591 | gadget_for_each_ep (ep, dev->gadget) { |
1592 | struct ep_data *data; | ||
1593 | 1592 | ||
1594 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 1593 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
1595 | if (!data) | 1594 | if (!data) |
1596 | goto enomem; | 1595 | goto enomem0; |
1597 | data->state = STATE_EP_DISABLED; | 1596 | data->state = STATE_EP_DISABLED; |
1598 | init_MUTEX (&data->lock); | 1597 | init_MUTEX (&data->lock); |
1599 | init_waitqueue_head (&data->wait); | 1598 | init_waitqueue_head (&data->wait); |
@@ -1608,21 +1607,23 @@ static int activate_ep_files (struct dev_data *dev) | |||
1608 | 1607 | ||
1609 | data->req = usb_ep_alloc_request (ep, GFP_KERNEL); | 1608 | data->req = usb_ep_alloc_request (ep, GFP_KERNEL); |
1610 | if (!data->req) | 1609 | if (!data->req) |
1611 | goto enomem; | 1610 | goto enomem1; |
1612 | 1611 | ||
1613 | data->inode = gadgetfs_create_file (dev->sb, data->name, | 1612 | data->inode = gadgetfs_create_file (dev->sb, data->name, |
1614 | data, &ep_config_operations, | 1613 | data, &ep_config_operations, |
1615 | &data->dentry); | 1614 | &data->dentry); |
1616 | if (!data->inode) { | 1615 | if (!data->inode) |
1617 | usb_ep_free_request(ep, data->req); | 1616 | goto enomem2; |
1618 | kfree (data); | ||
1619 | goto enomem; | ||
1620 | } | ||
1621 | list_add_tail (&data->epfiles, &dev->epfiles); | 1617 | list_add_tail (&data->epfiles, &dev->epfiles); |
1622 | } | 1618 | } |
1623 | return 0; | 1619 | return 0; |
1624 | 1620 | ||
1625 | enomem: | 1621 | enomem2: |
1622 | usb_ep_free_request (ep, data->req); | ||
1623 | enomem1: | ||
1624 | put_dev (dev); | ||
1625 | kfree (data); | ||
1626 | enomem0: | ||
1626 | DBG (dev, "%s enomem\n", __FUNCTION__); | 1627 | DBG (dev, "%s enomem\n", __FUNCTION__); |
1627 | destroy_ep_files (dev); | 1628 | destroy_ep_files (dev); |
1628 | return -ENOMEM; | 1629 | return -ENOMEM; |
@@ -1793,7 +1794,7 @@ static struct usb_gadget_driver probe_driver = { | |||
1793 | * | 1794 | * |
1794 | * After initialization, the device stays active for as long as that | 1795 | * After initialization, the device stays active for as long as that |
1795 | * $CHIP file is open. Events may then be read from that descriptor, | 1796 | * $CHIP file is open. Events may then be read from that descriptor, |
1796 | * such configuration notifications. More complex drivers will handle | 1797 | * such as configuration notifications. More complex drivers will handle |
1797 | * some control requests in user space. | 1798 | * some control requests in user space. |
1798 | */ | 1799 | */ |
1799 | 1800 | ||
@@ -2033,12 +2034,10 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) | |||
2033 | NULL, &simple_dir_operations, | 2034 | NULL, &simple_dir_operations, |
2034 | S_IFDIR | S_IRUGO | S_IXUGO); | 2035 | S_IFDIR | S_IRUGO | S_IXUGO); |
2035 | if (!inode) | 2036 | if (!inode) |
2036 | return -ENOMEM; | 2037 | goto enomem0; |
2037 | inode->i_op = &simple_dir_inode_operations; | 2038 | inode->i_op = &simple_dir_inode_operations; |
2038 | if (!(d = d_alloc_root (inode))) { | 2039 | if (!(d = d_alloc_root (inode))) |
2039 | iput (inode); | 2040 | goto enomem1; |
2040 | return -ENOMEM; | ||
2041 | } | ||
2042 | sb->s_root = d; | 2041 | sb->s_root = d; |
2043 | 2042 | ||
2044 | /* the ep0 file is named after the controller we expect; | 2043 | /* the ep0 file is named after the controller we expect; |
@@ -2046,29 +2045,36 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) | |||
2046 | */ | 2045 | */ |
2047 | dev = dev_new (); | 2046 | dev = dev_new (); |
2048 | if (!dev) | 2047 | if (!dev) |
2049 | return -ENOMEM; | 2048 | goto enomem2; |
2050 | 2049 | ||
2051 | dev->sb = sb; | 2050 | dev->sb = sb; |
2052 | if (!(inode = gadgetfs_create_file (sb, CHIP, | 2051 | if (!gadgetfs_create_file (sb, CHIP, |
2053 | dev, &dev_init_operations, | 2052 | dev, &dev_init_operations, |
2054 | &dev->dentry))) { | 2053 | &dev->dentry)) |
2055 | put_dev(dev); | 2054 | goto enomem3; |
2056 | return -ENOMEM; | ||
2057 | } | ||
2058 | 2055 | ||
2059 | /* other endpoint files are available after hardware setup, | 2056 | /* other endpoint files are available after hardware setup, |
2060 | * from binding to a controller. | 2057 | * from binding to a controller. |
2061 | */ | 2058 | */ |
2062 | the_device = dev; | 2059 | the_device = dev; |
2063 | return 0; | 2060 | return 0; |
2061 | |||
2062 | enomem3: | ||
2063 | put_dev (dev); | ||
2064 | enomem2: | ||
2065 | dput (d); | ||
2066 | enomem1: | ||
2067 | iput (inode); | ||
2068 | enomem0: | ||
2069 | return -ENOMEM; | ||
2064 | } | 2070 | } |
2065 | 2071 | ||
2066 | /* "mount -t gadgetfs path /dev/gadget" ends up here */ | 2072 | /* "mount -t gadgetfs path /dev/gadget" ends up here */ |
2067 | static struct super_block * | 2073 | static int |
2068 | gadgetfs_get_sb (struct file_system_type *t, int flags, | 2074 | gadgetfs_get_sb (struct file_system_type *t, int flags, |
2069 | const char *path, void *opts) | 2075 | const char *path, void *opts, struct vfsmount *mnt) |
2070 | { | 2076 | { |
2071 | return get_sb_single (t, flags, opts, gadgetfs_fill_super); | 2077 | return get_sb_single (t, flags, opts, gadgetfs_fill_super, mnt); |
2072 | } | 2078 | } |
2073 | 2079 | ||
2074 | static void | 2080 | static void |
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 0b9293493957..1facdea56a8a 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
@@ -2822,7 +2822,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) | |||
2822 | unsigned long resource, len; | 2822 | unsigned long resource, len; |
2823 | void __iomem *base = NULL; | 2823 | void __iomem *base = NULL; |
2824 | int retval, i; | 2824 | int retval, i; |
2825 | char buf [8], *bufp; | ||
2826 | 2825 | ||
2827 | /* if you want to support more than one controller in a system, | 2826 | /* if you want to support more than one controller in a system, |
2828 | * usb_gadget_driver_{register,unregister}() must change. | 2827 | * usb_gadget_driver_{register,unregister}() must change. |
@@ -2896,15 +2895,10 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) | |||
2896 | retval = -ENODEV; | 2895 | retval = -ENODEV; |
2897 | goto done; | 2896 | goto done; |
2898 | } | 2897 | } |
2899 | #ifndef __sparc__ | 2898 | |
2900 | scnprintf (buf, sizeof buf, "%d", pdev->irq); | ||
2901 | bufp = buf; | ||
2902 | #else | ||
2903 | bufp = __irq_itoa(pdev->irq); | ||
2904 | #endif | ||
2905 | if (request_irq (pdev->irq, net2280_irq, SA_SHIRQ, driver_name, dev) | 2899 | if (request_irq (pdev->irq, net2280_irq, SA_SHIRQ, driver_name, dev) |
2906 | != 0) { | 2900 | != 0) { |
2907 | ERROR (dev, "request interrupt %s failed\n", bufp); | 2901 | ERROR (dev, "request interrupt %d failed\n", pdev->irq); |
2908 | retval = -EBUSY; | 2902 | retval = -EBUSY; |
2909 | goto done; | 2903 | goto done; |
2910 | } | 2904 | } |
@@ -2953,8 +2947,8 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) | |||
2953 | 2947 | ||
2954 | /* done */ | 2948 | /* done */ |
2955 | INFO (dev, "%s\n", driver_desc); | 2949 | INFO (dev, "%s\n", driver_desc); |
2956 | INFO (dev, "irq %s, pci mem %p, chip rev %04x\n", | 2950 | INFO (dev, "irq %d, pci mem %p, chip rev %04x\n", |
2957 | bufp, base, dev->chiprev); | 2951 | pdev->irq, base, dev->chiprev); |
2958 | INFO (dev, "version: " DRIVER_VERSION "; dma %s\n", | 2952 | INFO (dev, "version: " DRIVER_VERSION "; dma %s\n", |
2959 | use_dma | 2953 | use_dma |
2960 | ? (use_dma_chaining ? "chaining" : "enabled") | 2954 | ? (use_dma_chaining ? "chaining" : "enabled") |
@@ -2972,6 +2966,22 @@ done: | |||
2972 | return retval; | 2966 | return retval; |
2973 | } | 2967 | } |
2974 | 2968 | ||
2969 | /* make sure the board is quiescent; otherwise it will continue | ||
2970 | * generating IRQs across the upcoming reboot. | ||
2971 | */ | ||
2972 | |||
2973 | static void net2280_shutdown (struct pci_dev *pdev) | ||
2974 | { | ||
2975 | struct net2280 *dev = pci_get_drvdata (pdev); | ||
2976 | |||
2977 | /* disable IRQs */ | ||
2978 | writel (0, &dev->regs->pciirqenb0); | ||
2979 | writel (0, &dev->regs->pciirqenb1); | ||
2980 | |||
2981 | /* disable the pullup so the host will think we're gone */ | ||
2982 | writel (0, &dev->usb->usbctl); | ||
2983 | } | ||
2984 | |||
2975 | 2985 | ||
2976 | /*-------------------------------------------------------------------------*/ | 2986 | /*-------------------------------------------------------------------------*/ |
2977 | 2987 | ||
@@ -3001,6 +3011,7 @@ static struct pci_driver net2280_pci_driver = { | |||
3001 | 3011 | ||
3002 | .probe = net2280_probe, | 3012 | .probe = net2280_probe, |
3003 | .remove = net2280_remove, | 3013 | .remove = net2280_remove, |
3014 | .shutdown = net2280_shutdown, | ||
3004 | 3015 | ||
3005 | /* FIXME add power management support */ | 3016 | /* FIXME add power management support */ |
3006 | }; | 3017 | }; |
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 680f7fc5b171..269ce7f4ad66 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c | |||
@@ -53,12 +53,14 @@ | |||
53 | #include <asm/mach-types.h> | 53 | #include <asm/mach-types.h> |
54 | #include <asm/unaligned.h> | 54 | #include <asm/unaligned.h> |
55 | #include <asm/hardware.h> | 55 | #include <asm/hardware.h> |
56 | #ifdef CONFIG_ARCH_PXA | ||
56 | #include <asm/arch/pxa-regs.h> | 57 | #include <asm/arch/pxa-regs.h> |
58 | #endif | ||
57 | 59 | ||
58 | #include <linux/usb_ch9.h> | 60 | #include <linux/usb_ch9.h> |
59 | #include <linux/usb_gadget.h> | 61 | #include <linux/usb_gadget.h> |
60 | 62 | ||
61 | #include <asm/arch/udc.h> | 63 | #include <asm/arch/hardware/intel_udc.h> |
62 | 64 | ||
63 | 65 | ||
64 | /* | 66 | /* |
@@ -545,6 +547,7 @@ write_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) | |||
545 | count = req->req.length; | 547 | count = req->req.length; |
546 | done (ep, req, 0); | 548 | done (ep, req, 0); |
547 | ep0_idle(ep->dev); | 549 | ep0_idle(ep->dev); |
550 | #ifndef CONFIG_ARCH_IXP4XX | ||
548 | #if 1 | 551 | #if 1 |
549 | /* This seems to get rid of lost status irqs in some cases: | 552 | /* This seems to get rid of lost status irqs in some cases: |
550 | * host responds quickly, or next request involves config | 553 | * host responds quickly, or next request involves config |
@@ -565,6 +568,7 @@ write_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) | |||
565 | } while (count); | 568 | } while (count); |
566 | } | 569 | } |
567 | #endif | 570 | #endif |
571 | #endif | ||
568 | } else if (ep->dev->req_pending) | 572 | } else if (ep->dev->req_pending) |
569 | ep0start(ep->dev, 0, "IN"); | 573 | ep0start(ep->dev, 0, "IN"); |
570 | return is_short; | 574 | return is_short; |
@@ -1585,7 +1589,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) | |||
1585 | int retval; | 1589 | int retval; |
1586 | 1590 | ||
1587 | if (!driver | 1591 | if (!driver |
1588 | || driver->speed != USB_SPEED_FULL | 1592 | || driver->speed < USB_SPEED_FULL |
1589 | || !driver->bind | 1593 | || !driver->bind |
1590 | || !driver->unbind | 1594 | || !driver->unbind |
1591 | || !driver->disconnect | 1595 | || !driver->disconnect |
@@ -2427,6 +2431,7 @@ static struct pxa2xx_udc memory = { | |||
2427 | #define PXA210_B1 0x00000123 | 2431 | #define PXA210_B1 0x00000123 |
2428 | #define PXA210_B0 0x00000122 | 2432 | #define PXA210_B0 0x00000122 |
2429 | #define IXP425_A0 0x000001c1 | 2433 | #define IXP425_A0 0x000001c1 |
2434 | #define IXP465_AD 0x00000200 | ||
2430 | 2435 | ||
2431 | /* | 2436 | /* |
2432 | * probe - binds to the platform device | 2437 | * probe - binds to the platform device |
@@ -2463,6 +2468,8 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) | |||
2463 | break; | 2468 | break; |
2464 | #elif defined(CONFIG_ARCH_IXP4XX) | 2469 | #elif defined(CONFIG_ARCH_IXP4XX) |
2465 | case IXP425_A0: | 2470 | case IXP425_A0: |
2471 | case IXP465_AD: | ||
2472 | dev->has_cfr = 1; | ||
2466 | out_dma = 0; | 2473 | out_dma = 0; |
2467 | break; | 2474 | break; |
2468 | #endif | 2475 | #endif |
@@ -2575,10 +2582,12 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) | |||
2575 | free_irq(IRQ_USB, dev); | 2582 | free_irq(IRQ_USB, dev); |
2576 | dev->got_irq = 0; | 2583 | dev->got_irq = 0; |
2577 | } | 2584 | } |
2585 | #ifdef CONFIG_ARCH_LUBBOCK | ||
2578 | if (machine_is_lubbock()) { | 2586 | if (machine_is_lubbock()) { |
2579 | free_irq(LUBBOCK_USB_DISC_IRQ, dev); | 2587 | free_irq(LUBBOCK_USB_DISC_IRQ, dev); |
2580 | free_irq(LUBBOCK_USB_IRQ, dev); | 2588 | free_irq(LUBBOCK_USB_IRQ, dev); |
2581 | } | 2589 | } |
2590 | #endif | ||
2582 | platform_set_drvdata(pdev, NULL); | 2591 | platform_set_drvdata(pdev, NULL); |
2583 | the_controller = NULL; | 2592 | the_controller = NULL; |
2584 | return 0; | 2593 | return 0; |
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 6d6eaad73968..3ff6db7828a0 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c | |||
@@ -1,23 +1,23 @@ | |||
1 | /* | 1 | /* |
2 | * RNDIS MSG parser | 2 | * RNDIS MSG parser |
3 | * | 3 | * |
4 | * Version: $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $ | 4 | * Version: $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $ |
5 | * | 5 | * |
6 | * Authors: Benedikt Spranger, Pengutronix | 6 | * Authors: Benedikt Spranger, Pengutronix |
7 | * Robert Schwebel, Pengutronix | 7 | * Robert Schwebel, Pengutronix |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
11 | * version 2, as published by the Free Software Foundation. | 11 | * version 2, as published by the Free Software Foundation. |
12 | * | 12 | * |
13 | * This software was originally developed in conformance with | 13 | * This software was originally developed in conformance with |
14 | * Microsoft's Remote NDIS Specification License Agreement. | 14 | * Microsoft's Remote NDIS Specification License Agreement. |
15 | * | 15 | * |
16 | * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de> | 16 | * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de> |
17 | * Fixed message length bug in init_response | 17 | * Fixed message length bug in init_response |
18 | * | 18 | * |
19 | * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de> | 19 | * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de> |
20 | * Fixed rndis_rm_hdr length bug. | 20 | * Fixed rndis_rm_hdr length bug. |
21 | * | 21 | * |
22 | * Copyright (C) 2004 by David Brownell | 22 | * Copyright (C) 2004 by David Brownell |
23 | * updates to merge with Linux 2.6, better match RNDIS spec | 23 | * updates to merge with Linux 2.6, better match RNDIS spec |
@@ -82,7 +82,7 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length); | |||
82 | 82 | ||
83 | 83 | ||
84 | /* supported OIDs */ | 84 | /* supported OIDs */ |
85 | static const u32 oid_supported_list [] = | 85 | static const u32 oid_supported_list [] = |
86 | { | 86 | { |
87 | /* the general stuff */ | 87 | /* the general stuff */ |
88 | OID_GEN_SUPPORTED_LIST, | 88 | OID_GEN_SUPPORTED_LIST, |
@@ -103,7 +103,7 @@ static const u32 oid_supported_list [] = | |||
103 | #if 0 | 103 | #if 0 |
104 | OID_GEN_RNDIS_CONFIG_PARAMETER, | 104 | OID_GEN_RNDIS_CONFIG_PARAMETER, |
105 | #endif | 105 | #endif |
106 | 106 | ||
107 | /* the statistical stuff */ | 107 | /* the statistical stuff */ |
108 | OID_GEN_XMIT_OK, | 108 | OID_GEN_XMIT_OK, |
109 | OID_GEN_RCV_OK, | 109 | OID_GEN_RCV_OK, |
@@ -127,14 +127,14 @@ static const u32 oid_supported_list [] = | |||
127 | OID_GEN_TRANSMIT_QUEUE_LENGTH, | 127 | OID_GEN_TRANSMIT_QUEUE_LENGTH, |
128 | #endif /* RNDIS_OPTIONAL_STATS */ | 128 | #endif /* RNDIS_OPTIONAL_STATS */ |
129 | 129 | ||
130 | /* mandatory 802.3 */ | 130 | /* mandatory 802.3 */ |
131 | /* the general stuff */ | 131 | /* the general stuff */ |
132 | OID_802_3_PERMANENT_ADDRESS, | 132 | OID_802_3_PERMANENT_ADDRESS, |
133 | OID_802_3_CURRENT_ADDRESS, | 133 | OID_802_3_CURRENT_ADDRESS, |
134 | OID_802_3_MULTICAST_LIST, | 134 | OID_802_3_MULTICAST_LIST, |
135 | OID_802_3_MAC_OPTIONS, | 135 | OID_802_3_MAC_OPTIONS, |
136 | OID_802_3_MAXIMUM_LIST_SIZE, | 136 | OID_802_3_MAXIMUM_LIST_SIZE, |
137 | 137 | ||
138 | /* the statistical stuff */ | 138 | /* the statistical stuff */ |
139 | OID_802_3_RCV_ERROR_ALIGNMENT, | 139 | OID_802_3_RCV_ERROR_ALIGNMENT, |
140 | OID_802_3_XMIT_ONE_COLLISION, | 140 | OID_802_3_XMIT_ONE_COLLISION, |
@@ -172,8 +172,8 @@ static int | |||
172 | gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | 172 | gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, |
173 | rndis_resp_t *r) | 173 | rndis_resp_t *r) |
174 | { | 174 | { |
175 | int retval = -ENOTSUPP; | 175 | int retval = -ENOTSUPP; |
176 | u32 length = 4; /* usually */ | 176 | u32 length = 4; /* usually */ |
177 | __le32 *outbuf; | 177 | __le32 *outbuf; |
178 | int i, count; | 178 | int i, count; |
179 | rndis_query_cmplt_type *resp; | 179 | rndis_query_cmplt_type *resp; |
@@ -211,27 +211,27 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
211 | outbuf[i] = cpu_to_le32 (oid_supported_list[i]); | 211 | outbuf[i] = cpu_to_le32 (oid_supported_list[i]); |
212 | retval = 0; | 212 | retval = 0; |
213 | break; | 213 | break; |
214 | 214 | ||
215 | /* mandatory */ | 215 | /* mandatory */ |
216 | case OID_GEN_HARDWARE_STATUS: | 216 | case OID_GEN_HARDWARE_STATUS: |
217 | DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); | 217 | DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); |
218 | /* Bogus question! | 218 | /* Bogus question! |
219 | * Hardware must be ready to receive high level protocols. | 219 | * Hardware must be ready to receive high level protocols. |
220 | * BTW: | 220 | * BTW: |
221 | * reddite ergo quae sunt Caesaris Caesari | 221 | * reddite ergo quae sunt Caesaris Caesari |
222 | * et quae sunt Dei Deo! | 222 | * et quae sunt Dei Deo! |
223 | */ | 223 | */ |
224 | *outbuf = __constant_cpu_to_le32 (0); | 224 | *outbuf = __constant_cpu_to_le32 (0); |
225 | retval = 0; | 225 | retval = 0; |
226 | break; | 226 | break; |
227 | 227 | ||
228 | /* mandatory */ | 228 | /* mandatory */ |
229 | case OID_GEN_MEDIA_SUPPORTED: | 229 | case OID_GEN_MEDIA_SUPPORTED: |
230 | DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); | 230 | DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); |
231 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); | 231 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); |
232 | retval = 0; | 232 | retval = 0; |
233 | break; | 233 | break; |
234 | 234 | ||
235 | /* mandatory */ | 235 | /* mandatory */ |
236 | case OID_GEN_MEDIA_IN_USE: | 236 | case OID_GEN_MEDIA_IN_USE: |
237 | DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); | 237 | DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); |
@@ -239,7 +239,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
239 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); | 239 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); |
240 | retval = 0; | 240 | retval = 0; |
241 | break; | 241 | break; |
242 | 242 | ||
243 | /* mandatory */ | 243 | /* mandatory */ |
244 | case OID_GEN_MAXIMUM_FRAME_SIZE: | 244 | case OID_GEN_MAXIMUM_FRAME_SIZE: |
245 | DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); | 245 | DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); |
@@ -249,7 +249,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
249 | retval = 0; | 249 | retval = 0; |
250 | } | 250 | } |
251 | break; | 251 | break; |
252 | 252 | ||
253 | /* mandatory */ | 253 | /* mandatory */ |
254 | case OID_GEN_LINK_SPEED: | 254 | case OID_GEN_LINK_SPEED: |
255 | if (rndis_debug > 1) | 255 | if (rndis_debug > 1) |
@@ -272,7 +272,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
272 | retval = 0; | 272 | retval = 0; |
273 | } | 273 | } |
274 | break; | 274 | break; |
275 | 275 | ||
276 | /* mandatory */ | 276 | /* mandatory */ |
277 | case OID_GEN_RECEIVE_BLOCK_SIZE: | 277 | case OID_GEN_RECEIVE_BLOCK_SIZE: |
278 | DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); | 278 | DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); |
@@ -282,7 +282,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
282 | retval = 0; | 282 | retval = 0; |
283 | } | 283 | } |
284 | break; | 284 | break; |
285 | 285 | ||
286 | /* mandatory */ | 286 | /* mandatory */ |
287 | case OID_GEN_VENDOR_ID: | 287 | case OID_GEN_VENDOR_ID: |
288 | DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); | 288 | DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); |
@@ -290,7 +290,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
290 | rndis_per_dev_params [configNr].vendorID); | 290 | rndis_per_dev_params [configNr].vendorID); |
291 | retval = 0; | 291 | retval = 0; |
292 | break; | 292 | break; |
293 | 293 | ||
294 | /* mandatory */ | 294 | /* mandatory */ |
295 | case OID_GEN_VENDOR_DESCRIPTION: | 295 | case OID_GEN_VENDOR_DESCRIPTION: |
296 | DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); | 296 | DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); |
@@ -356,7 +356,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
356 | DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); | 356 | DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); |
357 | if (rndis_per_dev_params [configNr].stats) { | 357 | if (rndis_per_dev_params [configNr].stats) { |
358 | *outbuf = cpu_to_le32 ( | 358 | *outbuf = cpu_to_le32 ( |
359 | rndis_per_dev_params [configNr].stats->tx_packets - | 359 | rndis_per_dev_params [configNr].stats->tx_packets - |
360 | rndis_per_dev_params [configNr].stats->tx_errors - | 360 | rndis_per_dev_params [configNr].stats->tx_errors - |
361 | rndis_per_dev_params [configNr].stats->tx_dropped); | 361 | rndis_per_dev_params [configNr].stats->tx_dropped); |
362 | retval = 0; | 362 | retval = 0; |
@@ -369,13 +369,13 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
369 | DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); | 369 | DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); |
370 | if (rndis_per_dev_params [configNr].stats) { | 370 | if (rndis_per_dev_params [configNr].stats) { |
371 | *outbuf = cpu_to_le32 ( | 371 | *outbuf = cpu_to_le32 ( |
372 | rndis_per_dev_params [configNr].stats->rx_packets - | 372 | rndis_per_dev_params [configNr].stats->rx_packets - |
373 | rndis_per_dev_params [configNr].stats->rx_errors - | 373 | rndis_per_dev_params [configNr].stats->rx_errors - |
374 | rndis_per_dev_params [configNr].stats->rx_dropped); | 374 | rndis_per_dev_params [configNr].stats->rx_dropped); |
375 | retval = 0; | 375 | retval = 0; |
376 | } | 376 | } |
377 | break; | 377 | break; |
378 | 378 | ||
379 | /* mandatory */ | 379 | /* mandatory */ |
380 | case OID_GEN_XMIT_ERROR: | 380 | case OID_GEN_XMIT_ERROR: |
381 | if (rndis_debug > 1) | 381 | if (rndis_debug > 1) |
@@ -386,7 +386,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
386 | retval = 0; | 386 | retval = 0; |
387 | } | 387 | } |
388 | break; | 388 | break; |
389 | 389 | ||
390 | /* mandatory */ | 390 | /* mandatory */ |
391 | case OID_GEN_RCV_ERROR: | 391 | case OID_GEN_RCV_ERROR: |
392 | if (rndis_debug > 1) | 392 | if (rndis_debug > 1) |
@@ -397,7 +397,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
397 | retval = 0; | 397 | retval = 0; |
398 | } | 398 | } |
399 | break; | 399 | break; |
400 | 400 | ||
401 | /* mandatory */ | 401 | /* mandatory */ |
402 | case OID_GEN_RCV_NO_BUFFER: | 402 | case OID_GEN_RCV_NO_BUFFER: |
403 | DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); | 403 | DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); |
@@ -411,7 +411,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
411 | #ifdef RNDIS_OPTIONAL_STATS | 411 | #ifdef RNDIS_OPTIONAL_STATS |
412 | case OID_GEN_DIRECTED_BYTES_XMIT: | 412 | case OID_GEN_DIRECTED_BYTES_XMIT: |
413 | DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__); | 413 | DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__); |
414 | /* | 414 | /* |
415 | * Aunt Tilly's size of shoes | 415 | * Aunt Tilly's size of shoes |
416 | * minus antarctica count of penguins | 416 | * minus antarctica count of penguins |
417 | * divided by weight of Alpha Centauri | 417 | * divided by weight of Alpha Centauri |
@@ -419,7 +419,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
419 | if (rndis_per_dev_params [configNr].stats) { | 419 | if (rndis_per_dev_params [configNr].stats) { |
420 | *outbuf = cpu_to_le32 ( | 420 | *outbuf = cpu_to_le32 ( |
421 | (rndis_per_dev_params [configNr] | 421 | (rndis_per_dev_params [configNr] |
422 | .stats->tx_packets - | 422 | .stats->tx_packets - |
423 | rndis_per_dev_params [configNr] | 423 | rndis_per_dev_params [configNr] |
424 | .stats->tx_errors - | 424 | .stats->tx_errors - |
425 | rndis_per_dev_params [configNr] | 425 | rndis_per_dev_params [configNr] |
@@ -428,14 +428,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
428 | retval = 0; | 428 | retval = 0; |
429 | } | 429 | } |
430 | break; | 430 | break; |
431 | 431 | ||
432 | case OID_GEN_DIRECTED_FRAMES_XMIT: | 432 | case OID_GEN_DIRECTED_FRAMES_XMIT: |
433 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); | 433 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); |
434 | /* dito */ | 434 | /* dito */ |
435 | if (rndis_per_dev_params [configNr].stats) { | 435 | if (rndis_per_dev_params [configNr].stats) { |
436 | *outbuf = cpu_to_le32 ( | 436 | *outbuf = cpu_to_le32 ( |
437 | (rndis_per_dev_params [configNr] | 437 | (rndis_per_dev_params [configNr] |
438 | .stats->tx_packets - | 438 | .stats->tx_packets - |
439 | rndis_per_dev_params [configNr] | 439 | rndis_per_dev_params [configNr] |
440 | .stats->tx_errors - | 440 | .stats->tx_errors - |
441 | rndis_per_dev_params [configNr] | 441 | rndis_per_dev_params [configNr] |
@@ -444,7 +444,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
444 | retval = 0; | 444 | retval = 0; |
445 | } | 445 | } |
446 | break; | 446 | break; |
447 | 447 | ||
448 | case OID_GEN_MULTICAST_BYTES_XMIT: | 448 | case OID_GEN_MULTICAST_BYTES_XMIT: |
449 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); | 449 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); |
450 | if (rndis_per_dev_params [configNr].stats) { | 450 | if (rndis_per_dev_params [configNr].stats) { |
@@ -453,7 +453,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
453 | retval = 0; | 453 | retval = 0; |
454 | } | 454 | } |
455 | break; | 455 | break; |
456 | 456 | ||
457 | case OID_GEN_MULTICAST_FRAMES_XMIT: | 457 | case OID_GEN_MULTICAST_FRAMES_XMIT: |
458 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); | 458 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); |
459 | if (rndis_per_dev_params [configNr].stats) { | 459 | if (rndis_per_dev_params [configNr].stats) { |
@@ -462,7 +462,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
462 | retval = 0; | 462 | retval = 0; |
463 | } | 463 | } |
464 | break; | 464 | break; |
465 | 465 | ||
466 | case OID_GEN_BROADCAST_BYTES_XMIT: | 466 | case OID_GEN_BROADCAST_BYTES_XMIT: |
467 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); | 467 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); |
468 | if (rndis_per_dev_params [configNr].stats) { | 468 | if (rndis_per_dev_params [configNr].stats) { |
@@ -471,7 +471,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
471 | retval = 0; | 471 | retval = 0; |
472 | } | 472 | } |
473 | break; | 473 | break; |
474 | 474 | ||
475 | case OID_GEN_BROADCAST_FRAMES_XMIT: | 475 | case OID_GEN_BROADCAST_FRAMES_XMIT: |
476 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); | 476 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); |
477 | if (rndis_per_dev_params [configNr].stats) { | 477 | if (rndis_per_dev_params [configNr].stats) { |
@@ -480,19 +480,19 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
480 | retval = 0; | 480 | retval = 0; |
481 | } | 481 | } |
482 | break; | 482 | break; |
483 | 483 | ||
484 | case OID_GEN_DIRECTED_BYTES_RCV: | 484 | case OID_GEN_DIRECTED_BYTES_RCV: |
485 | DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); | 485 | DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); |
486 | *outbuf = __constant_cpu_to_le32 (0); | 486 | *outbuf = __constant_cpu_to_le32 (0); |
487 | retval = 0; | 487 | retval = 0; |
488 | break; | 488 | break; |
489 | 489 | ||
490 | case OID_GEN_DIRECTED_FRAMES_RCV: | 490 | case OID_GEN_DIRECTED_FRAMES_RCV: |
491 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); | 491 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); |
492 | *outbuf = __constant_cpu_to_le32 (0); | 492 | *outbuf = __constant_cpu_to_le32 (0); |
493 | retval = 0; | 493 | retval = 0; |
494 | break; | 494 | break; |
495 | 495 | ||
496 | case OID_GEN_MULTICAST_BYTES_RCV: | 496 | case OID_GEN_MULTICAST_BYTES_RCV: |
497 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); | 497 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); |
498 | if (rndis_per_dev_params [configNr].stats) { | 498 | if (rndis_per_dev_params [configNr].stats) { |
@@ -501,7 +501,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
501 | retval = 0; | 501 | retval = 0; |
502 | } | 502 | } |
503 | break; | 503 | break; |
504 | 504 | ||
505 | case OID_GEN_MULTICAST_FRAMES_RCV: | 505 | case OID_GEN_MULTICAST_FRAMES_RCV: |
506 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); | 506 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); |
507 | if (rndis_per_dev_params [configNr].stats) { | 507 | if (rndis_per_dev_params [configNr].stats) { |
@@ -510,7 +510,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
510 | retval = 0; | 510 | retval = 0; |
511 | } | 511 | } |
512 | break; | 512 | break; |
513 | 513 | ||
514 | case OID_GEN_BROADCAST_BYTES_RCV: | 514 | case OID_GEN_BROADCAST_BYTES_RCV: |
515 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); | 515 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); |
516 | if (rndis_per_dev_params [configNr].stats) { | 516 | if (rndis_per_dev_params [configNr].stats) { |
@@ -519,7 +519,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
519 | retval = 0; | 519 | retval = 0; |
520 | } | 520 | } |
521 | break; | 521 | break; |
522 | 522 | ||
523 | case OID_GEN_BROADCAST_FRAMES_RCV: | 523 | case OID_GEN_BROADCAST_FRAMES_RCV: |
524 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); | 524 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); |
525 | if (rndis_per_dev_params [configNr].stats) { | 525 | if (rndis_per_dev_params [configNr].stats) { |
@@ -528,7 +528,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
528 | retval = 0; | 528 | retval = 0; |
529 | } | 529 | } |
530 | break; | 530 | break; |
531 | 531 | ||
532 | case OID_GEN_RCV_CRC_ERROR: | 532 | case OID_GEN_RCV_CRC_ERROR: |
533 | DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); | 533 | DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); |
534 | if (rndis_per_dev_params [configNr].stats) { | 534 | if (rndis_per_dev_params [configNr].stats) { |
@@ -537,7 +537,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
537 | retval = 0; | 537 | retval = 0; |
538 | } | 538 | } |
539 | break; | 539 | break; |
540 | 540 | ||
541 | case OID_GEN_TRANSMIT_QUEUE_LENGTH: | 541 | case OID_GEN_TRANSMIT_QUEUE_LENGTH: |
542 | DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); | 542 | DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); |
543 | *outbuf = __constant_cpu_to_le32 (0); | 543 | *outbuf = __constant_cpu_to_le32 (0); |
@@ -558,7 +558,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
558 | retval = 0; | 558 | retval = 0; |
559 | } | 559 | } |
560 | break; | 560 | break; |
561 | 561 | ||
562 | /* mandatory */ | 562 | /* mandatory */ |
563 | case OID_802_3_CURRENT_ADDRESS: | 563 | case OID_802_3_CURRENT_ADDRESS: |
564 | DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); | 564 | DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); |
@@ -570,7 +570,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
570 | retval = 0; | 570 | retval = 0; |
571 | } | 571 | } |
572 | break; | 572 | break; |
573 | 573 | ||
574 | /* mandatory */ | 574 | /* mandatory */ |
575 | case OID_802_3_MULTICAST_LIST: | 575 | case OID_802_3_MULTICAST_LIST: |
576 | DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); | 576 | DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); |
@@ -578,7 +578,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
578 | *outbuf = __constant_cpu_to_le32 (0xE0000000); | 578 | *outbuf = __constant_cpu_to_le32 (0xE0000000); |
579 | retval = 0; | 579 | retval = 0; |
580 | break; | 580 | break; |
581 | 581 | ||
582 | /* mandatory */ | 582 | /* mandatory */ |
583 | case OID_802_3_MAXIMUM_LIST_SIZE: | 583 | case OID_802_3_MAXIMUM_LIST_SIZE: |
584 | DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); | 584 | DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); |
@@ -586,7 +586,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
586 | *outbuf = __constant_cpu_to_le32 (1); | 586 | *outbuf = __constant_cpu_to_le32 (1); |
587 | retval = 0; | 587 | retval = 0; |
588 | break; | 588 | break; |
589 | 589 | ||
590 | case OID_802_3_MAC_OPTIONS: | 590 | case OID_802_3_MAC_OPTIONS: |
591 | DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__); | 591 | DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__); |
592 | break; | 592 | break; |
@@ -602,56 +602,56 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
602 | retval = 0; | 602 | retval = 0; |
603 | } | 603 | } |
604 | break; | 604 | break; |
605 | 605 | ||
606 | /* mandatory */ | 606 | /* mandatory */ |
607 | case OID_802_3_XMIT_ONE_COLLISION: | 607 | case OID_802_3_XMIT_ONE_COLLISION: |
608 | DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); | 608 | DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); |
609 | *outbuf = __constant_cpu_to_le32 (0); | 609 | *outbuf = __constant_cpu_to_le32 (0); |
610 | retval = 0; | 610 | retval = 0; |
611 | break; | 611 | break; |
612 | 612 | ||
613 | /* mandatory */ | 613 | /* mandatory */ |
614 | case OID_802_3_XMIT_MORE_COLLISIONS: | 614 | case OID_802_3_XMIT_MORE_COLLISIONS: |
615 | DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); | 615 | DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); |
616 | *outbuf = __constant_cpu_to_le32 (0); | 616 | *outbuf = __constant_cpu_to_le32 (0); |
617 | retval = 0; | 617 | retval = 0; |
618 | break; | 618 | break; |
619 | 619 | ||
620 | #ifdef RNDIS_OPTIONAL_STATS | 620 | #ifdef RNDIS_OPTIONAL_STATS |
621 | case OID_802_3_XMIT_DEFERRED: | 621 | case OID_802_3_XMIT_DEFERRED: |
622 | DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__); | 622 | DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__); |
623 | /* TODO */ | 623 | /* TODO */ |
624 | break; | 624 | break; |
625 | 625 | ||
626 | case OID_802_3_XMIT_MAX_COLLISIONS: | 626 | case OID_802_3_XMIT_MAX_COLLISIONS: |
627 | DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__); | 627 | DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__); |
628 | /* TODO */ | 628 | /* TODO */ |
629 | break; | 629 | break; |
630 | 630 | ||
631 | case OID_802_3_RCV_OVERRUN: | 631 | case OID_802_3_RCV_OVERRUN: |
632 | DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__); | 632 | DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__); |
633 | /* TODO */ | 633 | /* TODO */ |
634 | break; | 634 | break; |
635 | 635 | ||
636 | case OID_802_3_XMIT_UNDERRUN: | 636 | case OID_802_3_XMIT_UNDERRUN: |
637 | DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__); | 637 | DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__); |
638 | /* TODO */ | 638 | /* TODO */ |
639 | break; | 639 | break; |
640 | 640 | ||
641 | case OID_802_3_XMIT_HEARTBEAT_FAILURE: | 641 | case OID_802_3_XMIT_HEARTBEAT_FAILURE: |
642 | DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__); | 642 | DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__); |
643 | /* TODO */ | 643 | /* TODO */ |
644 | break; | 644 | break; |
645 | 645 | ||
646 | case OID_802_3_XMIT_TIMES_CRS_LOST: | 646 | case OID_802_3_XMIT_TIMES_CRS_LOST: |
647 | DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__); | 647 | DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__); |
648 | /* TODO */ | 648 | /* TODO */ |
649 | break; | 649 | break; |
650 | 650 | ||
651 | case OID_802_3_XMIT_LATE_COLLISIONS: | 651 | case OID_802_3_XMIT_LATE_COLLISIONS: |
652 | DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__); | 652 | DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__); |
653 | /* TODO */ | 653 | /* TODO */ |
654 | break; | 654 | break; |
655 | #endif /* RNDIS_OPTIONAL_STATS */ | 655 | #endif /* RNDIS_OPTIONAL_STATS */ |
656 | 656 | ||
657 | #ifdef RNDIS_PM | 657 | #ifdef RNDIS_PM |
@@ -676,23 +676,23 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
676 | #endif | 676 | #endif |
677 | 677 | ||
678 | default: | 678 | default: |
679 | printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", | 679 | printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", |
680 | __FUNCTION__, OID); | 680 | __FUNCTION__, OID); |
681 | } | 681 | } |
682 | if (retval < 0) | 682 | if (retval < 0) |
683 | length = 0; | 683 | length = 0; |
684 | 684 | ||
685 | resp->InformationBufferLength = cpu_to_le32 (length); | 685 | resp->InformationBufferLength = cpu_to_le32 (length); |
686 | r->length = length + sizeof *resp; | 686 | r->length = length + sizeof *resp; |
687 | resp->MessageLength = cpu_to_le32 (r->length); | 687 | resp->MessageLength = cpu_to_le32 (r->length); |
688 | return retval; | 688 | return retval; |
689 | } | 689 | } |
690 | 690 | ||
691 | static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, | 691 | static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, |
692 | rndis_resp_t *r) | 692 | rndis_resp_t *r) |
693 | { | 693 | { |
694 | rndis_set_cmplt_type *resp; | 694 | rndis_set_cmplt_type *resp; |
695 | int i, retval = -ENOTSUPP; | 695 | int i, retval = -ENOTSUPP; |
696 | struct rndis_params *params; | 696 | struct rndis_params *params; |
697 | 697 | ||
698 | if (!r) | 698 | if (!r) |
@@ -745,9 +745,9 @@ update_linkstate: | |||
745 | netif_stop_queue (params->dev); | 745 | netif_stop_queue (params->dev); |
746 | } | 746 | } |
747 | break; | 747 | break; |
748 | 748 | ||
749 | case OID_802_3_MULTICAST_LIST: | 749 | case OID_802_3_MULTICAST_LIST: |
750 | /* I think we can ignore this */ | 750 | /* I think we can ignore this */ |
751 | DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); | 751 | DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); |
752 | retval = 0; | 752 | retval = 0; |
753 | break; | 753 | break; |
@@ -796,29 +796,29 @@ update_linkstate: | |||
796 | #endif /* RNDIS_PM */ | 796 | #endif /* RNDIS_PM */ |
797 | 797 | ||
798 | default: | 798 | default: |
799 | printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", | 799 | printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", |
800 | __FUNCTION__, OID, buf_len); | 800 | __FUNCTION__, OID, buf_len); |
801 | } | 801 | } |
802 | 802 | ||
803 | return retval; | 803 | return retval; |
804 | } | 804 | } |
805 | 805 | ||
806 | /* | 806 | /* |
807 | * Response Functions | 807 | * Response Functions |
808 | */ | 808 | */ |
809 | 809 | ||
810 | static int rndis_init_response (int configNr, rndis_init_msg_type *buf) | 810 | static int rndis_init_response (int configNr, rndis_init_msg_type *buf) |
811 | { | 811 | { |
812 | rndis_init_cmplt_type *resp; | 812 | rndis_init_cmplt_type *resp; |
813 | rndis_resp_t *r; | 813 | rndis_resp_t *r; |
814 | 814 | ||
815 | if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; | 815 | if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; |
816 | 816 | ||
817 | r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); | 817 | r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); |
818 | if (!r) | 818 | if (!r) |
819 | return -ENOMEM; | 819 | return -ENOMEM; |
820 | resp = (rndis_init_cmplt_type *) r->buf; | 820 | resp = (rndis_init_cmplt_type *) r->buf; |
821 | 821 | ||
822 | resp->MessageType = __constant_cpu_to_le32 ( | 822 | resp->MessageType = __constant_cpu_to_le32 ( |
823 | REMOTE_NDIS_INITIALIZE_CMPLT); | 823 | REMOTE_NDIS_INITIALIZE_CMPLT); |
824 | resp->MessageLength = __constant_cpu_to_le32 (52); | 824 | resp->MessageLength = __constant_cpu_to_le32 (52); |
@@ -837,11 +837,11 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf) | |||
837 | resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0); | 837 | resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0); |
838 | resp->AFListOffset = __constant_cpu_to_le32 (0); | 838 | resp->AFListOffset = __constant_cpu_to_le32 (0); |
839 | resp->AFListSize = __constant_cpu_to_le32 (0); | 839 | resp->AFListSize = __constant_cpu_to_le32 (0); |
840 | 840 | ||
841 | if (rndis_per_dev_params [configNr].ack) | 841 | if (rndis_per_dev_params [configNr].ack) |
842 | rndis_per_dev_params [configNr].ack ( | 842 | rndis_per_dev_params [configNr].ack ( |
843 | rndis_per_dev_params [configNr].dev); | 843 | rndis_per_dev_params [configNr].dev); |
844 | 844 | ||
845 | return 0; | 845 | return 0; |
846 | } | 846 | } |
847 | 847 | ||
@@ -849,10 +849,10 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) | |||
849 | { | 849 | { |
850 | rndis_query_cmplt_type *resp; | 850 | rndis_query_cmplt_type *resp; |
851 | rndis_resp_t *r; | 851 | rndis_resp_t *r; |
852 | 852 | ||
853 | // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID)); | 853 | // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID)); |
854 | if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; | 854 | if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; |
855 | 855 | ||
856 | /* | 856 | /* |
857 | * we need more memory: | 857 | * we need more memory: |
858 | * gen_ndis_query_resp expects enough space for | 858 | * gen_ndis_query_resp expects enough space for |
@@ -864,10 +864,10 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) | |||
864 | if (!r) | 864 | if (!r) |
865 | return -ENOMEM; | 865 | return -ENOMEM; |
866 | resp = (rndis_query_cmplt_type *) r->buf; | 866 | resp = (rndis_query_cmplt_type *) r->buf; |
867 | 867 | ||
868 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); | 868 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); |
869 | resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ | 869 | resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ |
870 | 870 | ||
871 | if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), | 871 | if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), |
872 | le32_to_cpu(buf->InformationBufferOffset) | 872 | le32_to_cpu(buf->InformationBufferOffset) |
873 | + 8 + (u8 *) buf, | 873 | + 8 + (u8 *) buf, |
@@ -881,10 +881,10 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) | |||
881 | resp->InformationBufferOffset = __constant_cpu_to_le32 (0); | 881 | resp->InformationBufferOffset = __constant_cpu_to_le32 (0); |
882 | } else | 882 | } else |
883 | resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); | 883 | resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); |
884 | 884 | ||
885 | if (rndis_per_dev_params [configNr].ack) | 885 | if (rndis_per_dev_params [configNr].ack) |
886 | rndis_per_dev_params [configNr].ack ( | 886 | rndis_per_dev_params [configNr].ack ( |
887 | rndis_per_dev_params [configNr].dev); | 887 | rndis_per_dev_params [configNr].dev); |
888 | return 0; | 888 | return 0; |
889 | } | 889 | } |
890 | 890 | ||
@@ -893,7 +893,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) | |||
893 | u32 BufLength, BufOffset; | 893 | u32 BufLength, BufOffset; |
894 | rndis_set_cmplt_type *resp; | 894 | rndis_set_cmplt_type *resp; |
895 | rndis_resp_t *r; | 895 | rndis_resp_t *r; |
896 | 896 | ||
897 | r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); | 897 | r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); |
898 | if (!r) | 898 | if (!r) |
899 | return -ENOMEM; | 899 | return -ENOMEM; |
@@ -906,26 +906,27 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) | |||
906 | DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength); | 906 | DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength); |
907 | DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset); | 907 | DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset); |
908 | DEBUG("%s: InfoBuffer: ", __FUNCTION__); | 908 | DEBUG("%s: InfoBuffer: ", __FUNCTION__); |
909 | 909 | ||
910 | for (i = 0; i < BufLength; i++) { | 910 | for (i = 0; i < BufLength; i++) { |
911 | DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); | 911 | DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); |
912 | } | 912 | } |
913 | 913 | ||
914 | DEBUG ("\n"); | 914 | DEBUG ("\n"); |
915 | #endif | 915 | #endif |
916 | 916 | ||
917 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); | 917 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); |
918 | resp->MessageLength = __constant_cpu_to_le32 (16); | 918 | resp->MessageLength = __constant_cpu_to_le32 (16); |
919 | resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ | 919 | resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ |
920 | if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), | 920 | if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), |
921 | ((u8 *) buf) + 8 + BufOffset, BufLength, r)) | 921 | ((u8 *) buf) + 8 + BufOffset, BufLength, r)) |
922 | resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); | 922 | resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); |
923 | else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); | 923 | else |
924 | 924 | resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); | |
925 | |||
925 | if (rndis_per_dev_params [configNr].ack) | 926 | if (rndis_per_dev_params [configNr].ack) |
926 | rndis_per_dev_params [configNr].ack ( | 927 | rndis_per_dev_params [configNr].ack ( |
927 | rndis_per_dev_params [configNr].dev); | 928 | rndis_per_dev_params [configNr].dev); |
928 | 929 | ||
929 | return 0; | 930 | return 0; |
930 | } | 931 | } |
931 | 932 | ||
@@ -933,27 +934,27 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf) | |||
933 | { | 934 | { |
934 | rndis_reset_cmplt_type *resp; | 935 | rndis_reset_cmplt_type *resp; |
935 | rndis_resp_t *r; | 936 | rndis_resp_t *r; |
936 | 937 | ||
937 | r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); | 938 | r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); |
938 | if (!r) | 939 | if (!r) |
939 | return -ENOMEM; | 940 | return -ENOMEM; |
940 | resp = (rndis_reset_cmplt_type *) r->buf; | 941 | resp = (rndis_reset_cmplt_type *) r->buf; |
941 | 942 | ||
942 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); | 943 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); |
943 | resp->MessageLength = __constant_cpu_to_le32 (16); | 944 | resp->MessageLength = __constant_cpu_to_le32 (16); |
944 | resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); | 945 | resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); |
945 | /* resent information */ | 946 | /* resent information */ |
946 | resp->AddressingReset = __constant_cpu_to_le32 (1); | 947 | resp->AddressingReset = __constant_cpu_to_le32 (1); |
947 | 948 | ||
948 | if (rndis_per_dev_params [configNr].ack) | 949 | if (rndis_per_dev_params [configNr].ack) |
949 | rndis_per_dev_params [configNr].ack ( | 950 | rndis_per_dev_params [configNr].ack ( |
950 | rndis_per_dev_params [configNr].dev); | 951 | rndis_per_dev_params [configNr].dev); |
951 | 952 | ||
952 | return 0; | 953 | return 0; |
953 | } | 954 | } |
954 | 955 | ||
955 | static int rndis_keepalive_response (int configNr, | 956 | static int rndis_keepalive_response (int configNr, |
956 | rndis_keepalive_msg_type *buf) | 957 | rndis_keepalive_msg_type *buf) |
957 | { | 958 | { |
958 | rndis_keepalive_cmplt_type *resp; | 959 | rndis_keepalive_cmplt_type *resp; |
959 | rndis_resp_t *r; | 960 | rndis_resp_t *r; |
@@ -964,48 +965,48 @@ static int rndis_keepalive_response (int configNr, | |||
964 | if (!r) | 965 | if (!r) |
965 | return -ENOMEM; | 966 | return -ENOMEM; |
966 | resp = (rndis_keepalive_cmplt_type *) r->buf; | 967 | resp = (rndis_keepalive_cmplt_type *) r->buf; |
967 | 968 | ||
968 | resp->MessageType = __constant_cpu_to_le32 ( | 969 | resp->MessageType = __constant_cpu_to_le32 ( |
969 | REMOTE_NDIS_KEEPALIVE_CMPLT); | 970 | REMOTE_NDIS_KEEPALIVE_CMPLT); |
970 | resp->MessageLength = __constant_cpu_to_le32 (16); | 971 | resp->MessageLength = __constant_cpu_to_le32 (16); |
971 | resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ | 972 | resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ |
972 | resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); | 973 | resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); |
973 | 974 | ||
974 | if (rndis_per_dev_params [configNr].ack) | 975 | if (rndis_per_dev_params [configNr].ack) |
975 | rndis_per_dev_params [configNr].ack ( | 976 | rndis_per_dev_params [configNr].ack ( |
976 | rndis_per_dev_params [configNr].dev); | 977 | rndis_per_dev_params [configNr].dev); |
977 | 978 | ||
978 | return 0; | 979 | return 0; |
979 | } | 980 | } |
980 | 981 | ||
981 | 982 | ||
982 | /* | 983 | /* |
983 | * Device to Host Comunication | 984 | * Device to Host Comunication |
984 | */ | 985 | */ |
985 | static int rndis_indicate_status_msg (int configNr, u32 status) | 986 | static int rndis_indicate_status_msg (int configNr, u32 status) |
986 | { | 987 | { |
987 | rndis_indicate_status_msg_type *resp; | 988 | rndis_indicate_status_msg_type *resp; |
988 | rndis_resp_t *r; | 989 | rndis_resp_t *r; |
989 | 990 | ||
990 | if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED) | 991 | if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED) |
991 | return -ENOTSUPP; | 992 | return -ENOTSUPP; |
992 | 993 | ||
993 | r = rndis_add_response (configNr, | 994 | r = rndis_add_response (configNr, |
994 | sizeof (rndis_indicate_status_msg_type)); | 995 | sizeof (rndis_indicate_status_msg_type)); |
995 | if (!r) | 996 | if (!r) |
996 | return -ENOMEM; | 997 | return -ENOMEM; |
997 | resp = (rndis_indicate_status_msg_type *) r->buf; | 998 | resp = (rndis_indicate_status_msg_type *) r->buf; |
998 | 999 | ||
999 | resp->MessageType = __constant_cpu_to_le32 ( | 1000 | resp->MessageType = __constant_cpu_to_le32 ( |
1000 | REMOTE_NDIS_INDICATE_STATUS_MSG); | 1001 | REMOTE_NDIS_INDICATE_STATUS_MSG); |
1001 | resp->MessageLength = __constant_cpu_to_le32 (20); | 1002 | resp->MessageLength = __constant_cpu_to_le32 (20); |
1002 | resp->Status = cpu_to_le32 (status); | 1003 | resp->Status = cpu_to_le32 (status); |
1003 | resp->StatusBufferLength = __constant_cpu_to_le32 (0); | 1004 | resp->StatusBufferLength = __constant_cpu_to_le32 (0); |
1004 | resp->StatusBufferOffset = __constant_cpu_to_le32 (0); | 1005 | resp->StatusBufferOffset = __constant_cpu_to_le32 (0); |
1005 | 1006 | ||
1006 | if (rndis_per_dev_params [configNr].ack) | 1007 | if (rndis_per_dev_params [configNr].ack) |
1007 | rndis_per_dev_params [configNr].ack ( | 1008 | rndis_per_dev_params [configNr].ack ( |
1008 | rndis_per_dev_params [configNr].dev); | 1009 | rndis_per_dev_params [configNr].dev); |
1009 | return 0; | 1010 | return 0; |
1010 | } | 1011 | } |
1011 | 1012 | ||
@@ -1013,7 +1014,7 @@ int rndis_signal_connect (int configNr) | |||
1013 | { | 1014 | { |
1014 | rndis_per_dev_params [configNr].media_state | 1015 | rndis_per_dev_params [configNr].media_state |
1015 | = NDIS_MEDIA_STATE_CONNECTED; | 1016 | = NDIS_MEDIA_STATE_CONNECTED; |
1016 | return rndis_indicate_status_msg (configNr, | 1017 | return rndis_indicate_status_msg (configNr, |
1017 | RNDIS_STATUS_MEDIA_CONNECT); | 1018 | RNDIS_STATUS_MEDIA_CONNECT); |
1018 | } | 1019 | } |
1019 | 1020 | ||
@@ -1045,26 +1046,26 @@ void rndis_set_host_mac (int configNr, const u8 *addr) | |||
1045 | rndis_per_dev_params [configNr].host_mac = addr; | 1046 | rndis_per_dev_params [configNr].host_mac = addr; |
1046 | } | 1047 | } |
1047 | 1048 | ||
1048 | /* | 1049 | /* |
1049 | * Message Parser | 1050 | * Message Parser |
1050 | */ | 1051 | */ |
1051 | int rndis_msg_parser (u8 configNr, u8 *buf) | 1052 | int rndis_msg_parser (u8 configNr, u8 *buf) |
1052 | { | 1053 | { |
1053 | u32 MsgType, MsgLength; | 1054 | u32 MsgType, MsgLength; |
1054 | __le32 *tmp; | 1055 | __le32 *tmp; |
1055 | struct rndis_params *params; | 1056 | struct rndis_params *params; |
1056 | 1057 | ||
1057 | if (!buf) | 1058 | if (!buf) |
1058 | return -ENOMEM; | 1059 | return -ENOMEM; |
1059 | 1060 | ||
1060 | tmp = (__le32 *) buf; | 1061 | tmp = (__le32 *) buf; |
1061 | MsgType = le32_to_cpup(tmp++); | 1062 | MsgType = le32_to_cpup(tmp++); |
1062 | MsgLength = le32_to_cpup(tmp++); | 1063 | MsgLength = le32_to_cpup(tmp++); |
1063 | 1064 | ||
1064 | if (configNr >= RNDIS_MAX_CONFIGS) | 1065 | if (configNr >= RNDIS_MAX_CONFIGS) |
1065 | return -ENOTSUPP; | 1066 | return -ENOTSUPP; |
1066 | params = &rndis_per_dev_params [configNr]; | 1067 | params = &rndis_per_dev_params [configNr]; |
1067 | 1068 | ||
1068 | /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for | 1069 | /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for |
1069 | * rx/tx statistics and link status, in addition to KEEPALIVE traffic | 1070 | * rx/tx statistics and link status, in addition to KEEPALIVE traffic |
1070 | * and normal HC level polling to see if there's any IN traffic. | 1071 | * and normal HC level polling to see if there's any IN traffic. |
@@ -1073,12 +1074,12 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1073 | /* For USB: responses may take up to 10 seconds */ | 1074 | /* For USB: responses may take up to 10 seconds */ |
1074 | switch (MsgType) { | 1075 | switch (MsgType) { |
1075 | case REMOTE_NDIS_INITIALIZE_MSG: | 1076 | case REMOTE_NDIS_INITIALIZE_MSG: |
1076 | DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", | 1077 | DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", |
1077 | __FUNCTION__ ); | 1078 | __FUNCTION__ ); |
1078 | params->state = RNDIS_INITIALIZED; | 1079 | params->state = RNDIS_INITIALIZED; |
1079 | return rndis_init_response (configNr, | 1080 | return rndis_init_response (configNr, |
1080 | (rndis_init_msg_type *) buf); | 1081 | (rndis_init_msg_type *) buf); |
1081 | 1082 | ||
1082 | case REMOTE_NDIS_HALT_MSG: | 1083 | case REMOTE_NDIS_HALT_MSG: |
1083 | DEBUG("%s: REMOTE_NDIS_HALT_MSG\n", | 1084 | DEBUG("%s: REMOTE_NDIS_HALT_MSG\n", |
1084 | __FUNCTION__ ); | 1085 | __FUNCTION__ ); |
@@ -1088,37 +1089,37 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1088 | netif_stop_queue (params->dev); | 1089 | netif_stop_queue (params->dev); |
1089 | } | 1090 | } |
1090 | return 0; | 1091 | return 0; |
1091 | 1092 | ||
1092 | case REMOTE_NDIS_QUERY_MSG: | 1093 | case REMOTE_NDIS_QUERY_MSG: |
1093 | return rndis_query_response (configNr, | 1094 | return rndis_query_response (configNr, |
1094 | (rndis_query_msg_type *) buf); | 1095 | (rndis_query_msg_type *) buf); |
1095 | 1096 | ||
1096 | case REMOTE_NDIS_SET_MSG: | 1097 | case REMOTE_NDIS_SET_MSG: |
1097 | return rndis_set_response (configNr, | 1098 | return rndis_set_response (configNr, |
1098 | (rndis_set_msg_type *) buf); | 1099 | (rndis_set_msg_type *) buf); |
1099 | 1100 | ||
1100 | case REMOTE_NDIS_RESET_MSG: | 1101 | case REMOTE_NDIS_RESET_MSG: |
1101 | DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", | 1102 | DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", |
1102 | __FUNCTION__ ); | 1103 | __FUNCTION__ ); |
1103 | return rndis_reset_response (configNr, | 1104 | return rndis_reset_response (configNr, |
1104 | (rndis_reset_msg_type *) buf); | 1105 | (rndis_reset_msg_type *) buf); |
1105 | 1106 | ||
1106 | case REMOTE_NDIS_KEEPALIVE_MSG: | 1107 | case REMOTE_NDIS_KEEPALIVE_MSG: |
1107 | /* For USB: host does this every 5 seconds */ | 1108 | /* For USB: host does this every 5 seconds */ |
1108 | if (rndis_debug > 1) | 1109 | if (rndis_debug > 1) |
1109 | DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", | 1110 | DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", |
1110 | __FUNCTION__ ); | 1111 | __FUNCTION__ ); |
1111 | return rndis_keepalive_response (configNr, | 1112 | return rndis_keepalive_response (configNr, |
1112 | (rndis_keepalive_msg_type *) | 1113 | (rndis_keepalive_msg_type *) |
1113 | buf); | 1114 | buf); |
1114 | 1115 | ||
1115 | default: | 1116 | default: |
1116 | /* At least Windows XP emits some undefined RNDIS messages. | 1117 | /* At least Windows XP emits some undefined RNDIS messages. |
1117 | * In one case those messages seemed to relate to the host | 1118 | * In one case those messages seemed to relate to the host |
1118 | * suspending itself. | 1119 | * suspending itself. |
1119 | */ | 1120 | */ |
1120 | printk (KERN_WARNING | 1121 | printk (KERN_WARNING |
1121 | "%s: unknown RNDIS message 0x%08X len %d\n", | 1122 | "%s: unknown RNDIS message 0x%08X len %d\n", |
1122 | __FUNCTION__ , MsgType, MsgLength); | 1123 | __FUNCTION__ , MsgType, MsgLength); |
1123 | { | 1124 | { |
1124 | unsigned i; | 1125 | unsigned i; |
@@ -1142,14 +1143,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1142 | } | 1143 | } |
1143 | break; | 1144 | break; |
1144 | } | 1145 | } |
1145 | 1146 | ||
1146 | return -ENOTSUPP; | 1147 | return -ENOTSUPP; |
1147 | } | 1148 | } |
1148 | 1149 | ||
1149 | int rndis_register (int (* rndis_control_ack) (struct net_device *)) | 1150 | int rndis_register (int (* rndis_control_ack) (struct net_device *)) |
1150 | { | 1151 | { |
1151 | u8 i; | 1152 | u8 i; |
1152 | 1153 | ||
1153 | for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { | 1154 | for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { |
1154 | if (!rndis_per_dev_params [i].used) { | 1155 | if (!rndis_per_dev_params [i].used) { |
1155 | rndis_per_dev_params [i].used = 1; | 1156 | rndis_per_dev_params [i].used = 1; |
@@ -1159,32 +1160,32 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *)) | |||
1159 | } | 1160 | } |
1160 | } | 1161 | } |
1161 | DEBUG("failed\n"); | 1162 | DEBUG("failed\n"); |
1162 | 1163 | ||
1163 | return -1; | 1164 | return -1; |
1164 | } | 1165 | } |
1165 | 1166 | ||
1166 | void rndis_deregister (int configNr) | 1167 | void rndis_deregister (int configNr) |
1167 | { | 1168 | { |
1168 | DEBUG("%s: \n", __FUNCTION__ ); | 1169 | DEBUG("%s: \n", __FUNCTION__ ); |
1169 | 1170 | ||
1170 | if (configNr >= RNDIS_MAX_CONFIGS) return; | 1171 | if (configNr >= RNDIS_MAX_CONFIGS) return; |
1171 | rndis_per_dev_params [configNr].used = 0; | 1172 | rndis_per_dev_params [configNr].used = 0; |
1172 | 1173 | ||
1173 | return; | 1174 | return; |
1174 | } | 1175 | } |
1175 | 1176 | ||
1176 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, | 1177 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, |
1177 | struct net_device_stats *stats, | 1178 | struct net_device_stats *stats, |
1178 | u16 *cdc_filter) | 1179 | u16 *cdc_filter) |
1179 | { | 1180 | { |
1180 | DEBUG("%s:\n", __FUNCTION__ ); | 1181 | DEBUG("%s:\n", __FUNCTION__ ); |
1181 | if (!dev || !stats) return -1; | 1182 | if (!dev || !stats) return -1; |
1182 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; | 1183 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; |
1183 | 1184 | ||
1184 | rndis_per_dev_params [configNr].dev = dev; | 1185 | rndis_per_dev_params [configNr].dev = dev; |
1185 | rndis_per_dev_params [configNr].stats = stats; | 1186 | rndis_per_dev_params [configNr].stats = stats; |
1186 | rndis_per_dev_params [configNr].filter = cdc_filter; | 1187 | rndis_per_dev_params [configNr].filter = cdc_filter; |
1187 | 1188 | ||
1188 | return 0; | 1189 | return 0; |
1189 | } | 1190 | } |
1190 | 1191 | ||
@@ -1193,10 +1194,10 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) | |||
1193 | DEBUG("%s:\n", __FUNCTION__ ); | 1194 | DEBUG("%s:\n", __FUNCTION__ ); |
1194 | if (!vendorDescr) return -1; | 1195 | if (!vendorDescr) return -1; |
1195 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; | 1196 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; |
1196 | 1197 | ||
1197 | rndis_per_dev_params [configNr].vendorID = vendorID; | 1198 | rndis_per_dev_params [configNr].vendorID = vendorID; |
1198 | rndis_per_dev_params [configNr].vendorDescr = vendorDescr; | 1199 | rndis_per_dev_params [configNr].vendorDescr = vendorDescr; |
1199 | 1200 | ||
1200 | return 0; | 1201 | return 0; |
1201 | } | 1202 | } |
1202 | 1203 | ||
@@ -1204,10 +1205,10 @@ int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) | |||
1204 | { | 1205 | { |
1205 | DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed); | 1206 | DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed); |
1206 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; | 1207 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; |
1207 | 1208 | ||
1208 | rndis_per_dev_params [configNr].medium = medium; | 1209 | rndis_per_dev_params [configNr].medium = medium; |
1209 | rndis_per_dev_params [configNr].speed = speed; | 1210 | rndis_per_dev_params [configNr].speed = speed; |
1210 | 1211 | ||
1211 | return 0; | 1212 | return 0; |
1212 | } | 1213 | } |
1213 | 1214 | ||
@@ -1229,9 +1230,9 @@ void rndis_free_response (int configNr, u8 *buf) | |||
1229 | { | 1230 | { |
1230 | rndis_resp_t *r; | 1231 | rndis_resp_t *r; |
1231 | struct list_head *act, *tmp; | 1232 | struct list_head *act, *tmp; |
1232 | 1233 | ||
1233 | list_for_each_safe (act, tmp, | 1234 | list_for_each_safe (act, tmp, |
1234 | &(rndis_per_dev_params [configNr].resp_queue)) | 1235 | &(rndis_per_dev_params [configNr].resp_queue)) |
1235 | { | 1236 | { |
1236 | r = list_entry (act, rndis_resp_t, list); | 1237 | r = list_entry (act, rndis_resp_t, list); |
1237 | if (r && r->buf == buf) { | 1238 | if (r && r->buf == buf) { |
@@ -1244,12 +1245,12 @@ void rndis_free_response (int configNr, u8 *buf) | |||
1244 | u8 *rndis_get_next_response (int configNr, u32 *length) | 1245 | u8 *rndis_get_next_response (int configNr, u32 *length) |
1245 | { | 1246 | { |
1246 | rndis_resp_t *r; | 1247 | rndis_resp_t *r; |
1247 | struct list_head *act, *tmp; | 1248 | struct list_head *act, *tmp; |
1248 | 1249 | ||
1249 | if (!length) return NULL; | 1250 | if (!length) return NULL; |
1250 | 1251 | ||
1251 | list_for_each_safe (act, tmp, | 1252 | list_for_each_safe (act, tmp, |
1252 | &(rndis_per_dev_params [configNr].resp_queue)) | 1253 | &(rndis_per_dev_params [configNr].resp_queue)) |
1253 | { | 1254 | { |
1254 | r = list_entry (act, rndis_resp_t, list); | 1255 | r = list_entry (act, rndis_resp_t, list); |
1255 | if (!r->send) { | 1256 | if (!r->send) { |
@@ -1258,24 +1259,24 @@ u8 *rndis_get_next_response (int configNr, u32 *length) | |||
1258 | return r->buf; | 1259 | return r->buf; |
1259 | } | 1260 | } |
1260 | } | 1261 | } |
1261 | 1262 | ||
1262 | return NULL; | 1263 | return NULL; |
1263 | } | 1264 | } |
1264 | 1265 | ||
1265 | static rndis_resp_t *rndis_add_response (int configNr, u32 length) | 1266 | static rndis_resp_t *rndis_add_response (int configNr, u32 length) |
1266 | { | 1267 | { |
1267 | rndis_resp_t *r; | 1268 | rndis_resp_t *r; |
1268 | 1269 | ||
1269 | /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ | 1270 | /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ |
1270 | r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC); | 1271 | r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC); |
1271 | if (!r) return NULL; | 1272 | if (!r) return NULL; |
1272 | 1273 | ||
1273 | r->buf = (u8 *) (r + 1); | 1274 | r->buf = (u8 *) (r + 1); |
1274 | r->length = length; | 1275 | r->length = length; |
1275 | r->send = 0; | 1276 | r->send = 0; |
1276 | 1277 | ||
1277 | list_add_tail (&r->list, | 1278 | list_add_tail (&r->list, |
1278 | &(rndis_per_dev_params [configNr].resp_queue)); | 1279 | &(rndis_per_dev_params [configNr].resp_queue)); |
1279 | return r; | 1280 | return r; |
1280 | } | 1281 | } |
1281 | 1282 | ||
@@ -1301,14 +1302,14 @@ int rndis_rm_hdr(struct sk_buff *skb) | |||
1301 | 1302 | ||
1302 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | 1303 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES |
1303 | 1304 | ||
1304 | static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, | 1305 | static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, |
1305 | void *data) | 1306 | void *data) |
1306 | { | 1307 | { |
1307 | char *out = page; | 1308 | char *out = page; |
1308 | int len; | 1309 | int len; |
1309 | rndis_params *param = (rndis_params *) data; | 1310 | rndis_params *param = (rndis_params *) data; |
1310 | 1311 | ||
1311 | out += snprintf (out, count, | 1312 | out += snprintf (out, count, |
1312 | "Config Nr. %d\n" | 1313 | "Config Nr. %d\n" |
1313 | "used : %s\n" | 1314 | "used : %s\n" |
1314 | "state : %s\n" | 1315 | "state : %s\n" |
@@ -1316,8 +1317,8 @@ static int rndis_proc_read (char *page, char **start, off_t off, int count, int | |||
1316 | "speed : %d\n" | 1317 | "speed : %d\n" |
1317 | "cable : %s\n" | 1318 | "cable : %s\n" |
1318 | "vendor ID : 0x%08X\n" | 1319 | "vendor ID : 0x%08X\n" |
1319 | "vendor : %s\n", | 1320 | "vendor : %s\n", |
1320 | param->confignr, (param->used) ? "y" : "n", | 1321 | param->confignr, (param->used) ? "y" : "n", |
1321 | ({ char *s = "?"; | 1322 | ({ char *s = "?"; |
1322 | switch (param->state) { | 1323 | switch (param->state) { |
1323 | case RNDIS_UNINITIALIZED: | 1324 | case RNDIS_UNINITIALIZED: |
@@ -1327,32 +1328,32 @@ static int rndis_proc_read (char *page, char **start, off_t off, int count, int | |||
1327 | case RNDIS_DATA_INITIALIZED: | 1328 | case RNDIS_DATA_INITIALIZED: |
1328 | s = "RNDIS_DATA_INITIALIZED"; break; | 1329 | s = "RNDIS_DATA_INITIALIZED"; break; |
1329 | }; s; }), | 1330 | }; s; }), |
1330 | param->medium, | 1331 | param->medium, |
1331 | (param->media_state) ? 0 : param->speed*100, | 1332 | (param->media_state) ? 0 : param->speed*100, |
1332 | (param->media_state) ? "disconnected" : "connected", | 1333 | (param->media_state) ? "disconnected" : "connected", |
1333 | param->vendorID, param->vendorDescr); | 1334 | param->vendorID, param->vendorDescr); |
1334 | 1335 | ||
1335 | len = out - page; | 1336 | len = out - page; |
1336 | len -= off; | 1337 | len -= off; |
1337 | 1338 | ||
1338 | if (len < count) { | 1339 | if (len < count) { |
1339 | *eof = 1; | 1340 | *eof = 1; |
1340 | if (len <= 0) | 1341 | if (len <= 0) |
1341 | return 0; | 1342 | return 0; |
1342 | } else | 1343 | } else |
1343 | len = count; | 1344 | len = count; |
1344 | 1345 | ||
1345 | *start = page + off; | 1346 | *start = page + off; |
1346 | return len; | 1347 | return len; |
1347 | } | 1348 | } |
1348 | 1349 | ||
1349 | static int rndis_proc_write (struct file *file, const char __user *buffer, | 1350 | static int rndis_proc_write (struct file *file, const char __user *buffer, |
1350 | unsigned long count, void *data) | 1351 | unsigned long count, void *data) |
1351 | { | 1352 | { |
1352 | rndis_params *p = data; | 1353 | rndis_params *p = data; |
1353 | u32 speed = 0; | 1354 | u32 speed = 0; |
1354 | int i, fl_speed = 0; | 1355 | int i, fl_speed = 0; |
1355 | 1356 | ||
1356 | for (i = 0; i < count; i++) { | 1357 | for (i = 0; i < count; i++) { |
1357 | char c; | 1358 | char c; |
1358 | if (get_user(c, buffer)) | 1359 | if (get_user(c, buffer)) |
@@ -1379,15 +1380,15 @@ static int rndis_proc_write (struct file *file, const char __user *buffer, | |||
1379 | case 'd': | 1380 | case 'd': |
1380 | rndis_signal_disconnect(p->confignr); | 1381 | rndis_signal_disconnect(p->confignr); |
1381 | break; | 1382 | break; |
1382 | default: | 1383 | default: |
1383 | if (fl_speed) p->speed = speed; | 1384 | if (fl_speed) p->speed = speed; |
1384 | else DEBUG ("%c is not valid\n", c); | 1385 | else DEBUG ("%c is not valid\n", c); |
1385 | break; | 1386 | break; |
1386 | } | 1387 | } |
1387 | 1388 | ||
1388 | buffer++; | 1389 | buffer++; |
1389 | } | 1390 | } |
1390 | 1391 | ||
1391 | return count; | 1392 | return count; |
1392 | } | 1393 | } |
1393 | 1394 | ||
@@ -1408,7 +1409,7 @@ int __init rndis_init (void) | |||
1408 | 1409 | ||
1409 | sprintf (name, NAME_TEMPLATE, i); | 1410 | sprintf (name, NAME_TEMPLATE, i); |
1410 | if (!(rndis_connect_state [i] | 1411 | if (!(rndis_connect_state [i] |
1411 | = create_proc_entry (name, 0660, NULL))) | 1412 | = create_proc_entry (name, 0660, NULL))) |
1412 | { | 1413 | { |
1413 | DEBUG ("%s :remove entries", __FUNCTION__); | 1414 | DEBUG ("%s :remove entries", __FUNCTION__); |
1414 | while (i) { | 1415 | while (i) { |
@@ -1432,7 +1433,7 @@ int __init rndis_init (void) | |||
1432 | = NDIS_MEDIA_STATE_DISCONNECTED; | 1433 | = NDIS_MEDIA_STATE_DISCONNECTED; |
1433 | INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue)); | 1434 | INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue)); |
1434 | } | 1435 | } |
1435 | 1436 | ||
1436 | return 0; | 1437 | return 0; |
1437 | } | 1438 | } |
1438 | 1439 | ||
@@ -1441,7 +1442,7 @@ void rndis_exit (void) | |||
1441 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | 1442 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES |
1442 | u8 i; | 1443 | u8 i; |
1443 | char name [20]; | 1444 | char name [20]; |
1444 | 1445 | ||
1445 | for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { | 1446 | for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { |
1446 | sprintf (name, NAME_TEMPLATE, i); | 1447 | sprintf (name, NAME_TEMPLATE, i); |
1447 | remove_proc_entry (name, NULL); | 1448 | remove_proc_entry (name, NULL); |
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index 95b4c6326100..2956608be751 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h | |||
@@ -1,15 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * RNDIS Definitions for Remote NDIS | 2 | * RNDIS Definitions for Remote NDIS |
3 | * | 3 | * |
4 | * Version: $Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $ | 4 | * Version: $Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $ |
5 | * | 5 | * |
6 | * Authors: Benedikt Spranger, Pengutronix | 6 | * Authors: Benedikt Spranger, Pengutronix |
7 | * Robert Schwebel, Pengutronix | 7 | * Robert Schwebel, Pengutronix |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
11 | * version 2, as published by the Free Software Foundation. | 11 | * version 2, as published by the Free Software Foundation. |
12 | * | 12 | * |
13 | * This software was originally developed in conformance with | 13 | * This software was originally developed in conformance with |
14 | * Microsoft's Remote NDIS Specification License Agreement. | 14 | * Microsoft's Remote NDIS Specification License Agreement. |
15 | */ | 15 | */ |
@@ -34,7 +34,7 @@ | |||
34 | #define RNDIS_STATUS_MEDIA_CONNECT 0x4001000BU /* Device connected */ | 34 | #define RNDIS_STATUS_MEDIA_CONNECT 0x4001000BU /* Device connected */ |
35 | #define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CU /* Device disconnected */ | 35 | #define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CU /* Device disconnected */ |
36 | /* For all not specified status messages: | 36 | /* For all not specified status messages: |
37 | * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx | 37 | * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx |
38 | */ | 38 | */ |
39 | 39 | ||
40 | /* Message Set for Connectionless (802.3) Devices */ | 40 | /* Message Set for Connectionless (802.3) Devices */ |
@@ -69,7 +69,7 @@ | |||
69 | #define OID_PNP_ENABLE_WAKE_UP 0xFD010106 | 69 | #define OID_PNP_ENABLE_WAKE_UP 0xFD010106 |
70 | 70 | ||
71 | 71 | ||
72 | typedef struct rndis_init_msg_type | 72 | typedef struct rndis_init_msg_type |
73 | { | 73 | { |
74 | __le32 MessageType; | 74 | __le32 MessageType; |
75 | __le32 MessageLength; | 75 | __le32 MessageLength; |
@@ -234,12 +234,12 @@ typedef struct rndis_params | |||
234 | 234 | ||
235 | const u8 *host_mac; | 235 | const u8 *host_mac; |
236 | u16 *filter; | 236 | u16 *filter; |
237 | struct net_device *dev; | 237 | struct net_device *dev; |
238 | struct net_device_stats *stats; | 238 | struct net_device_stats *stats; |
239 | 239 | ||
240 | u32 vendorID; | 240 | u32 vendorID; |
241 | const char *vendorDescr; | 241 | const char *vendorDescr; |
242 | int (*ack) (struct net_device *); | 242 | int (*ack) (struct net_device *); |
243 | struct list_head resp_queue; | 243 | struct list_head resp_queue; |
244 | } rndis_params; | 244 | } rndis_params; |
245 | 245 | ||
@@ -250,7 +250,7 @@ void rndis_deregister (int configNr); | |||
250 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, | 250 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, |
251 | struct net_device_stats *stats, | 251 | struct net_device_stats *stats, |
252 | u16 *cdc_filter); | 252 | u16 *cdc_filter); |
253 | int rndis_set_param_vendor (u8 configNr, u32 vendorID, | 253 | int rndis_set_param_vendor (u8 configNr, u32 vendorID, |
254 | const char *vendorDescr); | 254 | const char *vendorDescr); |
255 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); | 255 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); |
256 | void rndis_add_hdr (struct sk_buff *skb); | 256 | void rndis_add_hdr (struct sk_buff *skb); |
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index b992546c394d..9d6e1d295528 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -45,88 +45,16 @@ | |||
45 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
46 | 46 | ||
47 | #include <linux/usb_ch9.h> | 47 | #include <linux/usb_ch9.h> |
48 | #include <linux/usb_cdc.h> | 48 | #include <linux/usb/cdc.h> |
49 | #include <linux/usb_gadget.h> | 49 | #include <linux/usb_gadget.h> |
50 | 50 | ||
51 | #include "gadget_chips.h" | 51 | #include "gadget_chips.h" |
52 | 52 | ||
53 | 53 | ||
54 | /* Wait Cond */ | ||
55 | |||
56 | #define __wait_cond_interruptible(wq, condition, lock, flags, ret) \ | ||
57 | do { \ | ||
58 | wait_queue_t __wait; \ | ||
59 | init_waitqueue_entry(&__wait, current); \ | ||
60 | \ | ||
61 | add_wait_queue(&wq, &__wait); \ | ||
62 | for (;;) { \ | ||
63 | set_current_state(TASK_INTERRUPTIBLE); \ | ||
64 | if (condition) \ | ||
65 | break; \ | ||
66 | if (!signal_pending(current)) { \ | ||
67 | spin_unlock_irqrestore(lock, flags); \ | ||
68 | schedule(); \ | ||
69 | spin_lock_irqsave(lock, flags); \ | ||
70 | continue; \ | ||
71 | } \ | ||
72 | ret = -ERESTARTSYS; \ | ||
73 | break; \ | ||
74 | } \ | ||
75 | current->state = TASK_RUNNING; \ | ||
76 | remove_wait_queue(&wq, &__wait); \ | ||
77 | } while (0) | ||
78 | |||
79 | #define wait_cond_interruptible(wq, condition, lock, flags) \ | ||
80 | ({ \ | ||
81 | int __ret = 0; \ | ||
82 | if (!(condition)) \ | ||
83 | __wait_cond_interruptible(wq, condition, lock, flags, \ | ||
84 | __ret); \ | ||
85 | __ret; \ | ||
86 | }) | ||
87 | |||
88 | #define __wait_cond_interruptible_timeout(wq, condition, lock, flags, \ | ||
89 | timeout, ret) \ | ||
90 | do { \ | ||
91 | signed long __timeout = timeout; \ | ||
92 | wait_queue_t __wait; \ | ||
93 | init_waitqueue_entry(&__wait, current); \ | ||
94 | \ | ||
95 | add_wait_queue(&wq, &__wait); \ | ||
96 | for (;;) { \ | ||
97 | set_current_state(TASK_INTERRUPTIBLE); \ | ||
98 | if (__timeout == 0) \ | ||
99 | break; \ | ||
100 | if (condition) \ | ||
101 | break; \ | ||
102 | if (!signal_pending(current)) { \ | ||
103 | spin_unlock_irqrestore(lock, flags); \ | ||
104 | __timeout = schedule_timeout(__timeout); \ | ||
105 | spin_lock_irqsave(lock, flags); \ | ||
106 | continue; \ | ||
107 | } \ | ||
108 | ret = -ERESTARTSYS; \ | ||
109 | break; \ | ||
110 | } \ | ||
111 | current->state = TASK_RUNNING; \ | ||
112 | remove_wait_queue(&wq, &__wait); \ | ||
113 | } while (0) | ||
114 | |||
115 | #define wait_cond_interruptible_timeout(wq, condition, lock, flags, \ | ||
116 | timeout) \ | ||
117 | ({ \ | ||
118 | int __ret = 0; \ | ||
119 | if (!(condition)) \ | ||
120 | __wait_cond_interruptible_timeout(wq, condition, lock, \ | ||
121 | flags, timeout, __ret); \ | ||
122 | __ret; \ | ||
123 | }) | ||
124 | |||
125 | |||
126 | /* Defines */ | 54 | /* Defines */ |
127 | 55 | ||
128 | #define GS_VERSION_STR "v2.0" | 56 | #define GS_VERSION_STR "v2.2" |
129 | #define GS_VERSION_NUM 0x0200 | 57 | #define GS_VERSION_NUM 0x0202 |
130 | 58 | ||
131 | #define GS_LONG_NAME "Gadget Serial" | 59 | #define GS_LONG_NAME "Gadget Serial" |
132 | #define GS_SHORT_NAME "g_serial" | 60 | #define GS_SHORT_NAME "g_serial" |
@@ -843,9 +771,19 @@ exit_unlock_dev: | |||
843 | /* | 771 | /* |
844 | * gs_close | 772 | * gs_close |
845 | */ | 773 | */ |
774 | |||
775 | #define GS_WRITE_FINISHED_EVENT_SAFELY(p) \ | ||
776 | ({ \ | ||
777 | int cond; \ | ||
778 | \ | ||
779 | spin_lock_irq(&(p)->port_lock); \ | ||
780 | cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \ | ||
781 | spin_unlock_irq(&(p)->port_lock); \ | ||
782 | cond; \ | ||
783 | }) | ||
784 | |||
846 | static void gs_close(struct tty_struct *tty, struct file *file) | 785 | static void gs_close(struct tty_struct *tty, struct file *file) |
847 | { | 786 | { |
848 | unsigned long flags; | ||
849 | struct gs_port *port = tty->driver_data; | 787 | struct gs_port *port = tty->driver_data; |
850 | struct semaphore *sem; | 788 | struct semaphore *sem; |
851 | 789 | ||
@@ -859,7 +797,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) | |||
859 | sem = &gs_open_close_sem[port->port_num]; | 797 | sem = &gs_open_close_sem[port->port_num]; |
860 | down(sem); | 798 | down(sem); |
861 | 799 | ||
862 | spin_lock_irqsave(&port->port_lock, flags); | 800 | spin_lock_irq(&port->port_lock); |
863 | 801 | ||
864 | if (port->port_open_count == 0) { | 802 | if (port->port_open_count == 0) { |
865 | printk(KERN_ERR | 803 | printk(KERN_ERR |
@@ -887,12 +825,11 @@ static void gs_close(struct tty_struct *tty, struct file *file) | |||
887 | /* wait for write buffer to drain, or */ | 825 | /* wait for write buffer to drain, or */ |
888 | /* at most GS_CLOSE_TIMEOUT seconds */ | 826 | /* at most GS_CLOSE_TIMEOUT seconds */ |
889 | if (gs_buf_data_avail(port->port_write_buf) > 0) { | 827 | if (gs_buf_data_avail(port->port_write_buf) > 0) { |
890 | spin_unlock_irqrestore(&port->port_lock, flags); | 828 | spin_unlock_irq(&port->port_lock); |
891 | wait_cond_interruptible_timeout(port->port_write_wait, | 829 | wait_event_interruptible_timeout(port->port_write_wait, |
892 | port->port_dev == NULL | 830 | GS_WRITE_FINISHED_EVENT_SAFELY(port), |
893 | || gs_buf_data_avail(port->port_write_buf) == 0, | 831 | GS_CLOSE_TIMEOUT * HZ); |
894 | &port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ); | 832 | spin_lock_irq(&port->port_lock); |
895 | spin_lock_irqsave(&port->port_lock, flags); | ||
896 | } | 833 | } |
897 | 834 | ||
898 | /* free disconnected port on final close */ | 835 | /* free disconnected port on final close */ |
@@ -912,7 +849,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) | |||
912 | port->port_num, tty, file); | 849 | port->port_num, tty, file); |
913 | 850 | ||
914 | exit: | 851 | exit: |
915 | spin_unlock_irqrestore(&port->port_lock, flags); | 852 | spin_unlock_irq(&port->port_lock); |
916 | up(sem); | 853 | up(sem); |
917 | } | 854 | } |
918 | 855 | ||
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index e27b79a3c05f..b93d71d28db7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -47,12 +47,29 @@ config USB_EHCI_ROOT_HUB_TT | |||
47 | controller is needed. It's safe to say "y" even if your | 47 | controller is needed. It's safe to say "y" even if your |
48 | controller doesn't support this feature. | 48 | controller doesn't support this feature. |
49 | 49 | ||
50 | This supports the EHCI implementation from TransDimension Inc. | 50 | This supports the EHCI implementation that's originally |
51 | from ARC, and has since changed hands a few times. | ||
52 | |||
53 | config USB_EHCI_TT_NEWSCHED | ||
54 | bool "Improved Transaction Translator scheduling (EXPERIMENTAL)" | ||
55 | depends on USB_EHCI_HCD && EXPERIMENTAL | ||
56 | ---help--- | ||
57 | This changes the periodic scheduling code to fill more of the low | ||
58 | and full speed bandwidth available from the Transaction Translator | ||
59 | (TT) in USB 2.0 hubs. Without this, only one transfer will be | ||
60 | issued in each microframe, significantly reducing the number of | ||
61 | periodic low/fullspeed transfers possible. | ||
62 | |||
63 | If you have multiple periodic low/fullspeed devices connected to a | ||
64 | highspeed USB hub which is connected to a highspeed USB Host | ||
65 | Controller, and some of those devices will not work correctly | ||
66 | (possibly due to "ENOSPC" or "-28" errors), say Y. | ||
67 | |||
68 | If unsure, say N. | ||
51 | 69 | ||
52 | config USB_ISP116X_HCD | 70 | config USB_ISP116X_HCD |
53 | tristate "ISP116X HCD support" | 71 | tristate "ISP116X HCD support" |
54 | depends on USB | 72 | depends on USB |
55 | default N | ||
56 | ---help--- | 73 | ---help--- |
57 | The ISP1160 and ISP1161 chips are USB host controllers. Enable this | 74 | The ISP1160 and ISP1161 chips are USB host controllers. Enable this |
58 | option if your board has this chip. If unsure, say N. | 75 | option if your board has this chip. If unsure, say N. |
@@ -127,7 +144,6 @@ config USB_UHCI_HCD | |||
127 | config USB_SL811_HCD | 144 | config USB_SL811_HCD |
128 | tristate "SL811HS HCD support" | 145 | tristate "SL811HS HCD support" |
129 | depends on USB | 146 | depends on USB |
130 | default N | ||
131 | help | 147 | help |
132 | The SL811HS is a single-port USB controller that supports either | 148 | The SL811HS is a single-port USB controller that supports either |
133 | host side or peripheral side roles. Enable this option if your | 149 | host side or peripheral side roles. Enable this option if your |
@@ -140,7 +156,6 @@ config USB_SL811_HCD | |||
140 | config USB_SL811_CS | 156 | config USB_SL811_CS |
141 | tristate "CF/PCMCIA support for SL811HS HCD" | 157 | tristate "CF/PCMCIA support for SL811HS HCD" |
142 | depends on USB_SL811_HCD && PCMCIA | 158 | depends on USB_SL811_HCD && PCMCIA |
143 | default N | ||
144 | help | 159 | help |
145 | Wraps a PCMCIA driver around the SL811HS HCD, supporting the RATOC | 160 | Wraps a PCMCIA driver around the SL811HS HCD, supporting the RATOC |
146 | REX-CFU1U CF card (often used with PDAs). If unsure, say N. | 161 | REX-CFU1U CF card (often used with PDAs). If unsure, say N. |
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 63eadeec1324..9b4697add313 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c | |||
@@ -16,10 +16,6 @@ | |||
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <asm/mach-au1x00/au1000.h> | 17 | #include <asm/mach-au1x00/au1000.h> |
18 | 18 | ||
19 | #ifndef CONFIG_SOC_AU1200 | ||
20 | #error "this Alchemy chip doesn't have EHCI" | ||
21 | #else /* Au1200 */ | ||
22 | |||
23 | #define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) | 19 | #define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) |
24 | #define USB_MCFG_PFEN (1<<31) | 20 | #define USB_MCFG_PFEN (1<<31) |
25 | #define USB_MCFG_RDCOMB (1<<30) | 21 | #define USB_MCFG_RDCOMB (1<<30) |
@@ -272,6 +268,8 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev) | |||
272 | return 0; | 268 | return 0; |
273 | } | 269 | } |
274 | */ | 270 | */ |
271 | MODULE_ALIAS("au1xxx-ehci"); | ||
272 | /* FIXME use "struct platform_driver" */ | ||
275 | static struct device_driver ehci_hcd_au1xxx_driver = { | 273 | static struct device_driver ehci_hcd_au1xxx_driver = { |
276 | .name = "au1xxx-ehci", | 274 | .name = "au1xxx-ehci", |
277 | .bus = &platform_bus_type, | 275 | .bus = &platform_bus_type, |
@@ -280,18 +278,3 @@ static struct device_driver ehci_hcd_au1xxx_driver = { | |||
280 | /*.suspend = ehci_hcd_au1xxx_drv_suspend, */ | 278 | /*.suspend = ehci_hcd_au1xxx_drv_suspend, */ |
281 | /*.resume = ehci_hcd_au1xxx_drv_resume, */ | 279 | /*.resume = ehci_hcd_au1xxx_drv_resume, */ |
282 | }; | 280 | }; |
283 | |||
284 | static int __init ehci_hcd_au1xxx_init(void) | ||
285 | { | ||
286 | pr_debug(DRIVER_INFO " (Au1xxx)\n"); | ||
287 | |||
288 | return driver_register(&ehci_hcd_au1xxx_driver); | ||
289 | } | ||
290 | |||
291 | static void __exit ehci_hcd_au1xxx_cleanup(void) | ||
292 | { | ||
293 | driver_unregister(&ehci_hcd_au1xxx_driver); | ||
294 | } | ||
295 | |||
296 | module_init(ehci_hcd_au1xxx_init); | ||
297 | module_exit(ehci_hcd_au1xxx_cleanup); | ||
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index f985f121a245..a49a689bf423 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -324,43 +324,12 @@ static int ehci_fsl_drv_remove(struct platform_device *pdev) | |||
324 | return 0; | 324 | return 0; |
325 | } | 325 | } |
326 | 326 | ||
327 | static struct platform_driver ehci_fsl_dr_driver = { | 327 | MODULE_ALIAS("fsl-ehci"); |
328 | .probe = ehci_fsl_drv_probe, | ||
329 | .remove = ehci_fsl_drv_remove, | ||
330 | .driver = { | ||
331 | .name = "fsl-usb2-dr", | ||
332 | }, | ||
333 | }; | ||
334 | 328 | ||
335 | static struct platform_driver ehci_fsl_mph_driver = { | 329 | static struct platform_driver ehci_fsl_driver = { |
336 | .probe = ehci_fsl_drv_probe, | 330 | .probe = ehci_fsl_drv_probe, |
337 | .remove = ehci_fsl_drv_remove, | 331 | .remove = ehci_fsl_drv_remove, |
338 | .driver = { | 332 | .driver = { |
339 | .name = "fsl-usb2-mph", | 333 | .name = "fsl-ehci", |
340 | }, | 334 | }, |
341 | }; | 335 | }; |
342 | |||
343 | static int __init ehci_fsl_init(void) | ||
344 | { | ||
345 | int retval; | ||
346 | |||
347 | pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", | ||
348 | hcd_name, | ||
349 | sizeof(struct ehci_qh), sizeof(struct ehci_qtd), | ||
350 | sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); | ||
351 | |||
352 | retval = platform_driver_register(&ehci_fsl_dr_driver); | ||
353 | if (retval) | ||
354 | return retval; | ||
355 | |||
356 | return platform_driver_register(&ehci_fsl_mph_driver); | ||
357 | } | ||
358 | |||
359 | static void __exit ehci_fsl_cleanup(void) | ||
360 | { | ||
361 | platform_driver_unregister(&ehci_fsl_mph_driver); | ||
362 | platform_driver_unregister(&ehci_fsl_dr_driver); | ||
363 | } | ||
364 | |||
365 | module_init(ehci_fsl_init); | ||
366 | module_exit(ehci_fsl_cleanup); | ||
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 79f2d8b9bfb6..9b37e508ada3 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -889,19 +889,59 @@ MODULE_LICENSE ("GPL"); | |||
889 | 889 | ||
890 | #ifdef CONFIG_PCI | 890 | #ifdef CONFIG_PCI |
891 | #include "ehci-pci.c" | 891 | #include "ehci-pci.c" |
892 | #define EHCI_BUS_GLUED | 892 | #define PCI_DRIVER ehci_pci_driver |
893 | #endif | 893 | #endif |
894 | 894 | ||
895 | #ifdef CONFIG_PPC_83xx | 895 | #ifdef CONFIG_PPC_83xx |
896 | #include "ehci-fsl.c" | 896 | #include "ehci-fsl.c" |
897 | #define EHCI_BUS_GLUED | 897 | #define PLATFORM_DRIVER ehci_fsl_driver |
898 | #endif | 898 | #endif |
899 | 899 | ||
900 | #ifdef CONFIG_SOC_AU1X00 | 900 | #ifdef CONFIG_SOC_AU1200 |
901 | #include "ehci-au1xxx.c" | 901 | #include "ehci-au1xxx.c" |
902 | #define EHCI_BUS_GLUED | 902 | #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver |
903 | #endif | 903 | #endif |
904 | 904 | ||
905 | #ifndef EHCI_BUS_GLUED | 905 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) |
906 | #error "missing bus glue for ehci-hcd" | 906 | #error "missing bus glue for ehci-hcd" |
907 | #endif | 907 | #endif |
908 | |||
909 | static int __init ehci_hcd_init(void) | ||
910 | { | ||
911 | int retval = 0; | ||
912 | |||
913 | pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", | ||
914 | hcd_name, | ||
915 | sizeof(struct ehci_qh), sizeof(struct ehci_qtd), | ||
916 | sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); | ||
917 | |||
918 | #ifdef PLATFORM_DRIVER | ||
919 | retval = platform_driver_register(&PLATFORM_DRIVER); | ||
920 | if (retval < 0) | ||
921 | return retval; | ||
922 | #endif | ||
923 | |||
924 | #ifdef PCI_DRIVER | ||
925 | retval = pci_register_driver(&PCI_DRIVER); | ||
926 | if (retval < 0) { | ||
927 | #ifdef PLATFORM_DRIVER | ||
928 | platform_driver_unregister(&PLATFORM_DRIVER); | ||
929 | #endif | ||
930 | } | ||
931 | #endif | ||
932 | |||
933 | return retval; | ||
934 | } | ||
935 | module_init(ehci_hcd_init); | ||
936 | |||
937 | static void __exit ehci_hcd_cleanup(void) | ||
938 | { | ||
939 | #ifdef PLATFORM_DRIVER | ||
940 | platform_driver_unregister(&PLATFORM_DRIVER); | ||
941 | #endif | ||
942 | #ifdef PCI_DRIVER | ||
943 | pci_unregister_driver(&PCI_DRIVER); | ||
944 | #endif | ||
945 | } | ||
946 | module_exit(ehci_hcd_cleanup); | ||
947 | |||
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index a1bd2bea6deb..cadffacd945b 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -76,6 +76,30 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
76 | dbg_hcs_params(ehci, "reset"); | 76 | dbg_hcs_params(ehci, "reset"); |
77 | dbg_hcc_params(ehci, "reset"); | 77 | dbg_hcc_params(ehci, "reset"); |
78 | 78 | ||
79 | /* ehci_init() causes memory for DMA transfers to be | ||
80 | * allocated. Thus, any vendor-specific workarounds based on | ||
81 | * limiting the type of memory used for DMA transfers must | ||
82 | * happen before ehci_init() is called. */ | ||
83 | switch (pdev->vendor) { | ||
84 | case PCI_VENDOR_ID_NVIDIA: | ||
85 | /* NVidia reports that certain chips don't handle | ||
86 | * QH, ITD, or SITD addresses above 2GB. (But TD, | ||
87 | * data buffer, and periodic schedule are normal.) | ||
88 | */ | ||
89 | switch (pdev->device) { | ||
90 | case 0x003c: /* MCP04 */ | ||
91 | case 0x005b: /* CK804 */ | ||
92 | case 0x00d8: /* CK8 */ | ||
93 | case 0x00e8: /* CK8S */ | ||
94 | if (pci_set_consistent_dma_mask(pdev, | ||
95 | DMA_31BIT_MASK) < 0) | ||
96 | ehci_warn(ehci, "can't enable NVidia " | ||
97 | "workaround for >2GB RAM\n"); | ||
98 | break; | ||
99 | } | ||
100 | break; | ||
101 | } | ||
102 | |||
79 | /* cache this readonly data; minimize chip reads */ | 103 | /* cache this readonly data; minimize chip reads */ |
80 | ehci->hcs_params = readl(&ehci->caps->hcs_params); | 104 | ehci->hcs_params = readl(&ehci->caps->hcs_params); |
81 | 105 | ||
@@ -88,8 +112,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
88 | if (retval) | 112 | if (retval) |
89 | return retval; | 113 | return retval; |
90 | 114 | ||
91 | /* NOTE: only the parts below this line are PCI-specific */ | ||
92 | |||
93 | switch (pdev->vendor) { | 115 | switch (pdev->vendor) { |
94 | case PCI_VENDOR_ID_TDI: | 116 | case PCI_VENDOR_ID_TDI: |
95 | if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { | 117 | if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { |
@@ -107,19 +129,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
107 | break; | 129 | break; |
108 | case PCI_VENDOR_ID_NVIDIA: | 130 | case PCI_VENDOR_ID_NVIDIA: |
109 | switch (pdev->device) { | 131 | switch (pdev->device) { |
110 | /* NVidia reports that certain chips don't handle | ||
111 | * QH, ITD, or SITD addresses above 2GB. (But TD, | ||
112 | * data buffer, and periodic schedule are normal.) | ||
113 | */ | ||
114 | case 0x003c: /* MCP04 */ | ||
115 | case 0x005b: /* CK804 */ | ||
116 | case 0x00d8: /* CK8 */ | ||
117 | case 0x00e8: /* CK8S */ | ||
118 | if (pci_set_consistent_dma_mask(pdev, | ||
119 | DMA_31BIT_MASK) < 0) | ||
120 | ehci_warn(ehci, "can't enable NVidia " | ||
121 | "workaround for >2GB RAM\n"); | ||
122 | break; | ||
123 | /* Some NForce2 chips have problems with selective suspend; | 132 | /* Some NForce2 chips have problems with selective suspend; |
124 | * fixed in newer silicon. | 133 | * fixed in newer silicon. |
125 | */ | 134 | */ |
@@ -370,23 +379,3 @@ static struct pci_driver ehci_pci_driver = { | |||
370 | .resume = usb_hcd_pci_resume, | 379 | .resume = usb_hcd_pci_resume, |
371 | #endif | 380 | #endif |
372 | }; | 381 | }; |
373 | |||
374 | static int __init ehci_hcd_pci_init(void) | ||
375 | { | ||
376 | if (usb_disabled()) | ||
377 | return -ENODEV; | ||
378 | |||
379 | pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", | ||
380 | hcd_name, | ||
381 | sizeof(struct ehci_qh), sizeof(struct ehci_qtd), | ||
382 | sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); | ||
383 | |||
384 | return pci_register_driver(&ehci_pci_driver); | ||
385 | } | ||
386 | module_init(ehci_hcd_pci_init); | ||
387 | |||
388 | static void __exit ehci_hcd_pci_cleanup(void) | ||
389 | { | ||
390 | pci_unregister_driver(&ehci_pci_driver); | ||
391 | } | ||
392 | module_exit(ehci_hcd_pci_cleanup); | ||
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 5871944e6145..4859900bd135 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -163,6 +163,190 @@ static int same_tt (struct usb_device *dev1, struct usb_device *dev2) | |||
163 | return 1; | 163 | return 1; |
164 | } | 164 | } |
165 | 165 | ||
166 | #ifdef CONFIG_USB_EHCI_TT_NEWSCHED | ||
167 | |||
168 | /* Which uframe does the low/fullspeed transfer start in? | ||
169 | * | ||
170 | * The parameter is the mask of ssplits in "H-frame" terms | ||
171 | * and this returns the transfer start uframe in "B-frame" terms, | ||
172 | * which allows both to match, e.g. a ssplit in "H-frame" uframe 0 | ||
173 | * will cause a transfer in "B-frame" uframe 0. "B-frames" lag | ||
174 | * "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7. | ||
175 | */ | ||
176 | static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __le32 mask) | ||
177 | { | ||
178 | unsigned char smask = QH_SMASK & le32_to_cpu(mask); | ||
179 | if (!smask) { | ||
180 | ehci_err(ehci, "invalid empty smask!\n"); | ||
181 | /* uframe 7 can't have bw so this will indicate failure */ | ||
182 | return 7; | ||
183 | } | ||
184 | return ffs(smask) - 1; | ||
185 | } | ||
186 | |||
187 | static const unsigned char | ||
188 | max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; | ||
189 | |||
190 | /* carryover low/fullspeed bandwidth that crosses uframe boundries */ | ||
191 | static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) | ||
192 | { | ||
193 | int i; | ||
194 | for (i=0; i<7; i++) { | ||
195 | if (max_tt_usecs[i] < tt_usecs[i]) { | ||
196 | tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; | ||
197 | tt_usecs[i] = max_tt_usecs[i]; | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | |||
202 | /* How many of the tt's periodic downstream 1000 usecs are allocated? | ||
203 | * | ||
204 | * While this measures the bandwidth in terms of usecs/uframe, | ||
205 | * the low/fullspeed bus has no notion of uframes, so any particular | ||
206 | * low/fullspeed transfer can "carry over" from one uframe to the next, | ||
207 | * since the TT just performs downstream transfers in sequence. | ||
208 | * | ||
209 | * For example two seperate 100 usec transfers can start in the same uframe, | ||
210 | * and the second one would "carry over" 75 usecs into the next uframe. | ||
211 | */ | ||
212 | static void | ||
213 | periodic_tt_usecs ( | ||
214 | struct ehci_hcd *ehci, | ||
215 | struct usb_device *dev, | ||
216 | unsigned frame, | ||
217 | unsigned short tt_usecs[8] | ||
218 | ) | ||
219 | { | ||
220 | __le32 *hw_p = &ehci->periodic [frame]; | ||
221 | union ehci_shadow *q = &ehci->pshadow [frame]; | ||
222 | unsigned char uf; | ||
223 | |||
224 | memset(tt_usecs, 0, 16); | ||
225 | |||
226 | while (q->ptr) { | ||
227 | switch (Q_NEXT_TYPE(*hw_p)) { | ||
228 | case Q_TYPE_ITD: | ||
229 | hw_p = &q->itd->hw_next; | ||
230 | q = &q->itd->itd_next; | ||
231 | continue; | ||
232 | case Q_TYPE_QH: | ||
233 | if (same_tt(dev, q->qh->dev)) { | ||
234 | uf = tt_start_uframe(ehci, q->qh->hw_info2); | ||
235 | tt_usecs[uf] += q->qh->tt_usecs; | ||
236 | } | ||
237 | hw_p = &q->qh->hw_next; | ||
238 | q = &q->qh->qh_next; | ||
239 | continue; | ||
240 | case Q_TYPE_SITD: | ||
241 | if (same_tt(dev, q->sitd->urb->dev)) { | ||
242 | uf = tt_start_uframe(ehci, q->sitd->hw_uframe); | ||
243 | tt_usecs[uf] += q->sitd->stream->tt_usecs; | ||
244 | } | ||
245 | hw_p = &q->sitd->hw_next; | ||
246 | q = &q->sitd->sitd_next; | ||
247 | continue; | ||
248 | // case Q_TYPE_FSTN: | ||
249 | default: | ||
250 | ehci_dbg(ehci, | ||
251 | "ignoring periodic frame %d FSTN\n", frame); | ||
252 | hw_p = &q->fstn->hw_next; | ||
253 | q = &q->fstn->fstn_next; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | carryover_tt_bandwidth(tt_usecs); | ||
258 | |||
259 | if (max_tt_usecs[7] < tt_usecs[7]) | ||
260 | ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n", | ||
261 | frame, tt_usecs[7] - max_tt_usecs[7]); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * Return true if the device's tt's downstream bus is available for a | ||
266 | * periodic transfer of the specified length (usecs), starting at the | ||
267 | * specified frame/uframe. Note that (as summarized in section 11.19 | ||
268 | * of the usb 2.0 spec) TTs can buffer multiple transactions for each | ||
269 | * uframe. | ||
270 | * | ||
271 | * The uframe parameter is when the fullspeed/lowspeed transfer | ||
272 | * should be executed in "B-frame" terms, which is the same as the | ||
273 | * highspeed ssplit's uframe (which is in "H-frame" terms). For example | ||
274 | * a ssplit in "H-frame" 0 causes a transfer in "B-frame" 0. | ||
275 | * See the EHCI spec sec 4.5 and fig 4.7. | ||
276 | * | ||
277 | * This checks if the full/lowspeed bus, at the specified starting uframe, | ||
278 | * has the specified bandwidth available, according to rules listed | ||
279 | * in USB 2.0 spec section 11.18.1 fig 11-60. | ||
280 | * | ||
281 | * This does not check if the transfer would exceed the max ssplit | ||
282 | * limit of 16, specified in USB 2.0 spec section 11.18.4 requirement #4, | ||
283 | * since proper scheduling limits ssplits to less than 16 per uframe. | ||
284 | */ | ||
285 | static int tt_available ( | ||
286 | struct ehci_hcd *ehci, | ||
287 | unsigned period, | ||
288 | struct usb_device *dev, | ||
289 | unsigned frame, | ||
290 | unsigned uframe, | ||
291 | u16 usecs | ||
292 | ) | ||
293 | { | ||
294 | if ((period == 0) || (uframe >= 7)) /* error */ | ||
295 | return 0; | ||
296 | |||
297 | for (; frame < ehci->periodic_size; frame += period) { | ||
298 | unsigned short tt_usecs[8]; | ||
299 | |||
300 | periodic_tt_usecs (ehci, dev, frame, tt_usecs); | ||
301 | |||
302 | ehci_vdbg(ehci, "tt frame %d check %d usecs start uframe %d in" | ||
303 | " schedule %d/%d/%d/%d/%d/%d/%d/%d\n", | ||
304 | frame, usecs, uframe, | ||
305 | tt_usecs[0], tt_usecs[1], tt_usecs[2], tt_usecs[3], | ||
306 | tt_usecs[4], tt_usecs[5], tt_usecs[6], tt_usecs[7]); | ||
307 | |||
308 | if (max_tt_usecs[uframe] <= tt_usecs[uframe]) { | ||
309 | ehci_vdbg(ehci, "frame %d uframe %d fully scheduled\n", | ||
310 | frame, uframe); | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | /* special case for isoc transfers larger than 125us: | ||
315 | * the first and each subsequent fully used uframe | ||
316 | * must be empty, so as to not illegally delay | ||
317 | * already scheduled transactions | ||
318 | */ | ||
319 | if (125 < usecs) { | ||
320 | int ufs = (usecs / 125) - 1; | ||
321 | int i; | ||
322 | for (i = uframe; i < (uframe + ufs) && i < 8; i++) | ||
323 | if (0 < tt_usecs[i]) { | ||
324 | ehci_vdbg(ehci, | ||
325 | "multi-uframe xfer can't fit " | ||
326 | "in frame %d uframe %d\n", | ||
327 | frame, i); | ||
328 | return 0; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | tt_usecs[uframe] += usecs; | ||
333 | |||
334 | carryover_tt_bandwidth(tt_usecs); | ||
335 | |||
336 | /* fail if the carryover pushed bw past the last uframe's limit */ | ||
337 | if (max_tt_usecs[7] < tt_usecs[7]) { | ||
338 | ehci_vdbg(ehci, | ||
339 | "tt unavailable usecs %d frame %d uframe %d\n", | ||
340 | usecs, frame, uframe); | ||
341 | return 0; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | return 1; | ||
346 | } | ||
347 | |||
348 | #else | ||
349 | |||
166 | /* return true iff the device's transaction translator is available | 350 | /* return true iff the device's transaction translator is available |
167 | * for a periodic transfer starting at the specified frame, using | 351 | * for a periodic transfer starting at the specified frame, using |
168 | * all the uframes in the mask. | 352 | * all the uframes in the mask. |
@@ -237,6 +421,8 @@ static int tt_no_collision ( | |||
237 | return 1; | 421 | return 1; |
238 | } | 422 | } |
239 | 423 | ||
424 | #endif /* CONFIG_USB_EHCI_TT_NEWSCHED */ | ||
425 | |||
240 | /*-------------------------------------------------------------------------*/ | 426 | /*-------------------------------------------------------------------------*/ |
241 | 427 | ||
242 | static int enable_periodic (struct ehci_hcd *ehci) | 428 | static int enable_periodic (struct ehci_hcd *ehci) |
@@ -481,7 +667,7 @@ static int check_intr_schedule ( | |||
481 | ) | 667 | ) |
482 | { | 668 | { |
483 | int retval = -ENOSPC; | 669 | int retval = -ENOSPC; |
484 | u8 mask; | 670 | u8 mask = 0; |
485 | 671 | ||
486 | if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ | 672 | if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ |
487 | goto done; | 673 | goto done; |
@@ -494,6 +680,24 @@ static int check_intr_schedule ( | |||
494 | goto done; | 680 | goto done; |
495 | } | 681 | } |
496 | 682 | ||
683 | #ifdef CONFIG_USB_EHCI_TT_NEWSCHED | ||
684 | if (tt_available (ehci, qh->period, qh->dev, frame, uframe, | ||
685 | qh->tt_usecs)) { | ||
686 | unsigned i; | ||
687 | |||
688 | /* TODO : this may need FSTN for SSPLIT in uframe 5. */ | ||
689 | for (i=uframe+1; i<8 && i<uframe+4; i++) | ||
690 | if (!check_period (ehci, frame, i, | ||
691 | qh->period, qh->c_usecs)) | ||
692 | goto done; | ||
693 | else | ||
694 | mask |= 1 << i; | ||
695 | |||
696 | retval = 0; | ||
697 | |||
698 | *c_maskp = cpu_to_le32 (mask << 8); | ||
699 | } | ||
700 | #else | ||
497 | /* Make sure this tt's buffer is also available for CSPLITs. | 701 | /* Make sure this tt's buffer is also available for CSPLITs. |
498 | * We pessimize a bit; probably the typical full speed case | 702 | * We pessimize a bit; probably the typical full speed case |
499 | * doesn't need the second CSPLIT. | 703 | * doesn't need the second CSPLIT. |
@@ -514,6 +718,7 @@ static int check_intr_schedule ( | |||
514 | goto done; | 718 | goto done; |
515 | retval = 0; | 719 | retval = 0; |
516 | } | 720 | } |
721 | #endif | ||
517 | done: | 722 | done: |
518 | return retval; | 723 | return retval; |
519 | } | 724 | } |
@@ -1047,12 +1252,21 @@ sitd_slot_ok ( | |||
1047 | frame = uframe >> 3; | 1252 | frame = uframe >> 3; |
1048 | uf = uframe & 7; | 1253 | uf = uframe & 7; |
1049 | 1254 | ||
1255 | #ifdef CONFIG_USB_EHCI_TT_NEWSCHED | ||
1256 | /* The tt's fullspeed bus bandwidth must be available. | ||
1257 | * tt_available scheduling guarantees 10+% for control/bulk. | ||
1258 | */ | ||
1259 | if (!tt_available (ehci, period_uframes << 3, | ||
1260 | stream->udev, frame, uf, stream->tt_usecs)) | ||
1261 | return 0; | ||
1262 | #else | ||
1050 | /* tt must be idle for start(s), any gap, and csplit. | 1263 | /* tt must be idle for start(s), any gap, and csplit. |
1051 | * assume scheduling slop leaves 10+% for control/bulk. | 1264 | * assume scheduling slop leaves 10+% for control/bulk. |
1052 | */ | 1265 | */ |
1053 | if (!tt_no_collision (ehci, period_uframes << 3, | 1266 | if (!tt_no_collision (ehci, period_uframes << 3, |
1054 | stream->udev, frame, mask)) | 1267 | stream->udev, frame, mask)) |
1055 | return 0; | 1268 | return 0; |
1269 | #endif | ||
1056 | 1270 | ||
1057 | /* check starts (OUT uses more than one) */ | 1271 | /* check starts (OUT uses more than one) */ |
1058 | max_used = 100 - stream->usecs; | 1272 | max_used = 100 - stream->usecs; |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index e99210b7909b..14386254c870 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -63,7 +63,7 @@ | |||
63 | #include <linux/init.h> | 63 | #include <linux/init.h> |
64 | #include <linux/list.h> | 64 | #include <linux/list.h> |
65 | #include <linux/usb.h> | 65 | #include <linux/usb.h> |
66 | #include <linux/usb_isp116x.h> | 66 | #include <linux/usb/isp116x.h> |
67 | #include <linux/platform_device.h> | 67 | #include <linux/platform_device.h> |
68 | 68 | ||
69 | #include <asm/io.h> | 69 | #include <asm/io.h> |
@@ -781,7 +781,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
781 | if (ep->branch < PERIODIC_SIZE) | 781 | if (ep->branch < PERIODIC_SIZE) |
782 | break; | 782 | break; |
783 | 783 | ||
784 | ret = ep->branch = balance(isp116x, ep->period, ep->load); | 784 | ep->branch = ret = balance(isp116x, ep->period, ep->load); |
785 | if (ret < 0) | 785 | if (ret < 0) |
786 | goto fail; | 786 | goto fail; |
787 | ret = 0; | 787 | ret = 0; |
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index acde8868da21..fafe7c1265b3 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c | |||
@@ -185,6 +185,9 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device | |||
185 | /* Select Power Management Mode */ | 185 | /* Select Power Management Mode */ |
186 | pxa27x_ohci_select_pmm(inf->port_mode); | 186 | pxa27x_ohci_select_pmm(inf->port_mode); |
187 | 187 | ||
188 | if (inf->power_budget) | ||
189 | hcd->power_budget = inf->power_budget; | ||
190 | |||
188 | ohci_hcd_init(hcd_to_ohci(hcd)); | 191 | ohci_hcd_init(hcd_to_ohci(hcd)); |
189 | 192 | ||
190 | retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT); | 193 | retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT); |
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index a92343052751..6b4bc3f2bd86 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include <linux/list.h> | 46 | #include <linux/list.h> |
47 | #include <linux/interrupt.h> | 47 | #include <linux/interrupt.h> |
48 | #include <linux/usb.h> | 48 | #include <linux/usb.h> |
49 | #include <linux/usb_sl811.h> | 49 | #include <linux/usb/sl811.h> |
50 | #include <linux/platform_device.h> | 50 | #include <linux/platform_device.h> |
51 | 51 | ||
52 | #include <asm/io.h> | 52 | #include <asm/io.h> |
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 302aa1ec312f..54f554e0f0ad 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <pcmcia/cisreg.h> | 27 | #include <pcmcia/cisreg.h> |
28 | #include <pcmcia/ds.h> | 28 | #include <pcmcia/ds.h> |
29 | 29 | ||
30 | #include <linux/usb_sl811.h> | 30 | #include <linux/usb/sl811.h> |
31 | 31 | ||
32 | MODULE_AUTHOR("Botond Botyanszki"); | 32 | MODULE_AUTHOR("Botond Botyanszki"); |
33 | MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6"); | 33 | MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6"); |
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index e1239319655c..6637a0e49978 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -98,6 +98,7 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) | |||
98 | char *out = buf; | 98 | char *out = buf; |
99 | struct uhci_td *td; | 99 | struct uhci_td *td; |
100 | int i, nactive, ninactive; | 100 | int i, nactive, ninactive; |
101 | char *ptype; | ||
101 | 102 | ||
102 | if (len < 200) | 103 | if (len < 200) |
103 | return 0; | 104 | return 0; |
@@ -110,13 +111,15 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) | |||
110 | (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); | 111 | (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); |
111 | 112 | ||
112 | switch (usb_pipetype(urbp->urb->pipe)) { | 113 | switch (usb_pipetype(urbp->urb->pipe)) { |
113 | case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO"); break; | 114 | case PIPE_ISOCHRONOUS: ptype = "ISO"; break; |
114 | case PIPE_INTERRUPT: out += sprintf(out, "INT"); break; | 115 | case PIPE_INTERRUPT: ptype = "INT"; break; |
115 | case PIPE_BULK: out += sprintf(out, "BLK"); break; | 116 | case PIPE_BULK: ptype = "BLK"; break; |
116 | case PIPE_CONTROL: out += sprintf(out, "CTL"); break; | 117 | default: |
118 | case PIPE_CONTROL: ptype = "CTL"; break; | ||
117 | } | 119 | } |
118 | 120 | ||
119 | out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : "")); | 121 | out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); |
122 | out += sprintf(out, " Actlen=%d", urbp->urb->actual_length); | ||
120 | 123 | ||
121 | if (urbp->urb->status != -EINPROGRESS) | 124 | if (urbp->urb->status != -EINPROGRESS) |
122 | out += sprintf(out, " Status=%d", urbp->urb->status); | 125 | out += sprintf(out, " Status=%d", urbp->urb->status); |
@@ -124,7 +127,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) | |||
124 | 127 | ||
125 | i = nactive = ninactive = 0; | 128 | i = nactive = ninactive = 0; |
126 | list_for_each_entry(td, &urbp->td_list, list) { | 129 | list_for_each_entry(td, &urbp->td_list, list) { |
127 | if (++i <= 10 || debug > 2) { | 130 | if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC && |
131 | (++i <= 10 || debug > 2)) { | ||
128 | out += sprintf(out, "%*s%d: ", space + 2, "", i); | 132 | out += sprintf(out, "%*s%d: ", space + 2, "", i); |
129 | out += uhci_show_td(td, out, len - (out - buf), 0); | 133 | out += uhci_show_td(td, out, len - (out - buf), 0); |
130 | } else { | 134 | } else { |
@@ -147,13 +151,27 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) | |||
147 | char *out = buf; | 151 | char *out = buf; |
148 | int i, nurbs; | 152 | int i, nurbs; |
149 | __le32 element = qh_element(qh); | 153 | __le32 element = qh_element(qh); |
154 | char *qtype; | ||
150 | 155 | ||
151 | /* Try to make sure there's enough memory */ | 156 | /* Try to make sure there's enough memory */ |
152 | if (len < 80 * 6) | 157 | if (len < 80 * 7) |
153 | return 0; | 158 | return 0; |
154 | 159 | ||
155 | out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n", space, "", | 160 | switch (qh->type) { |
156 | qh, le32_to_cpu(qh->link), le32_to_cpu(element)); | 161 | case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break; |
162 | case USB_ENDPOINT_XFER_INT: qtype = "INT"; break; | ||
163 | case USB_ENDPOINT_XFER_BULK: qtype = "BLK"; break; | ||
164 | case USB_ENDPOINT_XFER_CONTROL: qtype = "CTL"; break; | ||
165 | default: qtype = "Skel" ; break; | ||
166 | } | ||
167 | |||
168 | out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n", | ||
169 | space, "", qh, qtype, | ||
170 | le32_to_cpu(qh->link), le32_to_cpu(element)); | ||
171 | if (qh->type == USB_ENDPOINT_XFER_ISOC) | ||
172 | out += sprintf(out, "%*s period %d frame %x desc [%p]\n", | ||
173 | space, "", qh->period, qh->iso_frame, | ||
174 | qh->iso_packet_desc); | ||
157 | 175 | ||
158 | if (element & UHCI_PTR_QH) | 176 | if (element & UHCI_PTR_QH) |
159 | out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); | 177 | out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); |
@@ -261,7 +279,8 @@ static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len) | |||
261 | default: | 279 | default: |
262 | rh_state = "?"; break; | 280 | rh_state = "?"; break; |
263 | } | 281 | } |
264 | out += sprintf(out, "Root-hub state: %s\n", rh_state); | 282 | out += sprintf(out, "Root-hub state: %s FSBR: %d\n", |
283 | rh_state, uhci->fsbr_is_on); | ||
265 | return out - buf; | 284 | return out - buf; |
266 | } | 285 | } |
267 | 286 | ||
@@ -275,7 +294,7 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) | |||
275 | unsigned short portsc1, portsc2; | 294 | unsigned short portsc1, portsc2; |
276 | 295 | ||
277 | /* Try to make sure there's enough memory */ | 296 | /* Try to make sure there's enough memory */ |
278 | if (len < 80 * 6) | 297 | if (len < 80 * 9) |
279 | return 0; | 298 | return 0; |
280 | 299 | ||
281 | usbcmd = inw(io_addr + 0); | 300 | usbcmd = inw(io_addr + 0); |
@@ -314,6 +333,10 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) | |||
314 | out += sprintf(out, " sof = %02x\n", sof); | 333 | out += sprintf(out, " sof = %02x\n", sof); |
315 | out += uhci_show_sc(1, portsc1, out, len - (out - buf)); | 334 | out += uhci_show_sc(1, portsc1, out, len - (out - buf)); |
316 | out += uhci_show_sc(2, portsc2, out, len - (out - buf)); | 335 | out += uhci_show_sc(2, portsc2, out, len - (out - buf)); |
336 | out += sprintf(out, "Most recent frame: %x (%d) " | ||
337 | "Last ISO frame: %x (%d)\n", | ||
338 | uhci->frame_number, uhci->frame_number & 1023, | ||
339 | uhci->last_iso_frame, uhci->last_iso_frame & 1023); | ||
317 | 340 | ||
318 | return out - buf; | 341 | return out - buf; |
319 | } | 342 | } |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index d225e11f4055..7b48567622ef 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -13,7 +13,7 @@ | |||
13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface | 13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface |
14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). | 14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). |
15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) | 15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) |
16 | * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu | 16 | * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu |
17 | * | 17 | * |
18 | * Intel documents this fairly well, and as far as I know there | 18 | * Intel documents this fairly well, and as far as I know there |
19 | * are no royalties or anything like that, but even so there are | 19 | * are no royalties or anything like that, but even so there are |
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/smp_lock.h> | ||
35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
36 | #include <linux/unistd.h> | 35 | #include <linux/unistd.h> |
37 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
@@ -88,15 +87,6 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state); | |||
88 | static void wakeup_rh(struct uhci_hcd *uhci); | 87 | static void wakeup_rh(struct uhci_hcd *uhci); |
89 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | 88 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); |
90 | 89 | ||
91 | /* If a transfer is still active after this much time, turn off FSBR */ | ||
92 | #define IDLE_TIMEOUT msecs_to_jiffies(50) | ||
93 | #define FSBR_DELAY msecs_to_jiffies(50) | ||
94 | |||
95 | /* When we timeout an idle transfer for FSBR, we'll switch it over to */ | ||
96 | /* depth first traversal. We'll do it in groups of this number of TDs */ | ||
97 | /* to make sure it doesn't hog all of the bandwidth */ | ||
98 | #define DEPTH_INTERVAL 5 | ||
99 | |||
100 | #include "uhci-debug.c" | 90 | #include "uhci-debug.c" |
101 | #include "uhci-q.c" | 91 | #include "uhci-q.c" |
102 | #include "uhci-hub.c" | 92 | #include "uhci-hub.c" |
@@ -120,22 +110,29 @@ static void finish_reset(struct uhci_hcd *uhci) | |||
120 | uhci->is_stopped = UHCI_IS_STOPPED; | 110 | uhci->is_stopped = UHCI_IS_STOPPED; |
121 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; | 111 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; |
122 | uhci_to_hcd(uhci)->poll_rh = 0; | 112 | uhci_to_hcd(uhci)->poll_rh = 0; |
113 | |||
114 | uhci->dead = 0; /* Full reset resurrects the controller */ | ||
123 | } | 115 | } |
124 | 116 | ||
125 | /* | 117 | /* |
126 | * Last rites for a defunct/nonfunctional controller | 118 | * Last rites for a defunct/nonfunctional controller |
127 | * or one we don't want to use any more. | 119 | * or one we don't want to use any more. |
128 | */ | 120 | */ |
129 | static void hc_died(struct uhci_hcd *uhci) | 121 | static void uhci_hc_died(struct uhci_hcd *uhci) |
130 | { | 122 | { |
123 | uhci_get_current_frame_number(uhci); | ||
131 | uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); | 124 | uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); |
132 | finish_reset(uhci); | 125 | finish_reset(uhci); |
133 | uhci->hc_inaccessible = 1; | 126 | uhci->dead = 1; |
127 | |||
128 | /* The current frame may already be partway finished */ | ||
129 | ++uhci->frame_number; | ||
134 | } | 130 | } |
135 | 131 | ||
136 | /* | 132 | /* |
137 | * Initialize a controller that was newly discovered or has just been | 133 | * Initialize a controller that was newly discovered or has lost power |
138 | * resumed. In either case we can't be sure of its previous state. | 134 | * or otherwise been reset while it was suspended. In none of these cases |
135 | * can we be sure of its previous state. | ||
139 | */ | 136 | */ |
140 | static void check_and_reset_hc(struct uhci_hcd *uhci) | 137 | static void check_and_reset_hc(struct uhci_hcd *uhci) |
141 | { | 138 | { |
@@ -155,7 +152,8 @@ static void configure_hc(struct uhci_hcd *uhci) | |||
155 | outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD); | 152 | outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD); |
156 | 153 | ||
157 | /* Set the current frame number */ | 154 | /* Set the current frame number */ |
158 | outw(uhci->frame_number, uhci->io_addr + USBFRNUM); | 155 | outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER, |
156 | uhci->io_addr + USBFRNUM); | ||
159 | 157 | ||
160 | /* Mark controller as not halted before we enable interrupts */ | 158 | /* Mark controller as not halted before we enable interrupts */ |
161 | uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; | 159 | uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; |
@@ -207,7 +205,8 @@ __acquires(uhci->lock) | |||
207 | int int_enable; | 205 | int int_enable; |
208 | 206 | ||
209 | auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); | 207 | auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); |
210 | dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__, | 208 | dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, |
209 | "%s%s\n", __FUNCTION__, | ||
211 | (auto_stop ? " (auto-stop)" : "")); | 210 | (auto_stop ? " (auto-stop)" : "")); |
212 | 211 | ||
213 | /* If we get a suspend request when we're already auto-stopped | 212 | /* If we get a suspend request when we're already auto-stopped |
@@ -241,27 +240,27 @@ __acquires(uhci->lock) | |||
241 | spin_unlock_irq(&uhci->lock); | 240 | spin_unlock_irq(&uhci->lock); |
242 | msleep(1); | 241 | msleep(1); |
243 | spin_lock_irq(&uhci->lock); | 242 | spin_lock_irq(&uhci->lock); |
244 | if (uhci->hc_inaccessible) /* Died */ | 243 | if (uhci->dead) |
245 | return; | 244 | return; |
246 | } | 245 | } |
247 | if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) | 246 | if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) |
248 | dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); | 247 | dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev, |
248 | "Controller not stopped yet!\n"); | ||
249 | 249 | ||
250 | uhci_get_current_frame_number(uhci); | 250 | uhci_get_current_frame_number(uhci); |
251 | smp_wmb(); | ||
252 | 251 | ||
253 | uhci->rh_state = new_state; | 252 | uhci->rh_state = new_state; |
254 | uhci->is_stopped = UHCI_IS_STOPPED; | 253 | uhci->is_stopped = UHCI_IS_STOPPED; |
255 | uhci_to_hcd(uhci)->poll_rh = !int_enable; | 254 | uhci_to_hcd(uhci)->poll_rh = !int_enable; |
256 | 255 | ||
257 | uhci_scan_schedule(uhci, NULL); | 256 | uhci_scan_schedule(uhci, NULL); |
257 | uhci_fsbr_off(uhci); | ||
258 | } | 258 | } |
259 | 259 | ||
260 | static void start_rh(struct uhci_hcd *uhci) | 260 | static void start_rh(struct uhci_hcd *uhci) |
261 | { | 261 | { |
262 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; | 262 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; |
263 | uhci->is_stopped = 0; | 263 | uhci->is_stopped = 0; |
264 | smp_wmb(); | ||
265 | 264 | ||
266 | /* Mark it configured and running with a 64-byte max packet. | 265 | /* Mark it configured and running with a 64-byte max packet. |
267 | * All interrupts are enabled, even though RESUME won't do anything. | 266 | * All interrupts are enabled, even though RESUME won't do anything. |
@@ -278,7 +277,8 @@ static void wakeup_rh(struct uhci_hcd *uhci) | |||
278 | __releases(uhci->lock) | 277 | __releases(uhci->lock) |
279 | __acquires(uhci->lock) | 278 | __acquires(uhci->lock) |
280 | { | 279 | { |
281 | dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__, | 280 | dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, |
281 | "%s%s\n", __FUNCTION__, | ||
282 | uhci->rh_state == UHCI_RH_AUTO_STOPPED ? | 282 | uhci->rh_state == UHCI_RH_AUTO_STOPPED ? |
283 | " (auto-start)" : ""); | 283 | " (auto-start)" : ""); |
284 | 284 | ||
@@ -293,7 +293,7 @@ __acquires(uhci->lock) | |||
293 | spin_unlock_irq(&uhci->lock); | 293 | spin_unlock_irq(&uhci->lock); |
294 | msleep(20); | 294 | msleep(20); |
295 | spin_lock_irq(&uhci->lock); | 295 | spin_lock_irq(&uhci->lock); |
296 | if (uhci->hc_inaccessible) /* Died */ | 296 | if (uhci->dead) |
297 | return; | 297 | return; |
298 | 298 | ||
299 | /* End Global Resume and wait for EOP to be sent */ | 299 | /* End Global Resume and wait for EOP to be sent */ |
@@ -345,7 +345,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
345 | errbuf, ERRBUF_LEN); | 345 | errbuf, ERRBUF_LEN); |
346 | lprintk(errbuf); | 346 | lprintk(errbuf); |
347 | } | 347 | } |
348 | hc_died(uhci); | 348 | uhci_hc_died(uhci); |
349 | 349 | ||
350 | /* Force a callback in case there are | 350 | /* Force a callback in case there are |
351 | * pending unlinks */ | 351 | * pending unlinks */ |
@@ -368,12 +368,21 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
368 | 368 | ||
369 | /* | 369 | /* |
370 | * Store the current frame number in uhci->frame_number if the controller | 370 | * Store the current frame number in uhci->frame_number if the controller |
371 | * is runnning | 371 | * is runnning. Expand from 11 bits (of which we use only 10) to a |
372 | * full-sized integer. | ||
373 | * | ||
374 | * Like many other parts of the driver, this code relies on being polled | ||
375 | * more than once per second as long as the controller is running. | ||
372 | */ | 376 | */ |
373 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci) | 377 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci) |
374 | { | 378 | { |
375 | if (!uhci->is_stopped) | 379 | if (!uhci->is_stopped) { |
376 | uhci->frame_number = inw(uhci->io_addr + USBFRNUM); | 380 | unsigned delta; |
381 | |||
382 | delta = (inw(uhci->io_addr + USBFRNUM) - uhci->frame_number) & | ||
383 | (UHCI_NUMFRAMES - 1); | ||
384 | uhci->frame_number += delta; | ||
385 | } | ||
377 | } | 386 | } |
378 | 387 | ||
379 | /* | 388 | /* |
@@ -407,7 +416,7 @@ static void release_uhci(struct uhci_hcd *uhci) | |||
407 | uhci->frame, uhci->frame_dma_handle); | 416 | uhci->frame, uhci->frame_dma_handle); |
408 | } | 417 | } |
409 | 418 | ||
410 | static int uhci_reset(struct usb_hcd *hcd) | 419 | static int uhci_init(struct usb_hcd *hcd) |
411 | { | 420 | { |
412 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 421 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
413 | unsigned io_size = (unsigned) hcd->rsrc_len; | 422 | unsigned io_size = (unsigned) hcd->rsrc_len; |
@@ -459,7 +468,7 @@ static void uhci_shutdown(struct pci_dev *pdev) | |||
459 | { | 468 | { |
460 | struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev); | 469 | struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev); |
461 | 470 | ||
462 | hc_died(hcd_to_uhci(hcd)); | 471 | uhci_hc_died(hcd_to_uhci(hcd)); |
463 | } | 472 | } |
464 | 473 | ||
465 | /* | 474 | /* |
@@ -487,14 +496,10 @@ static int uhci_start(struct usb_hcd *hcd) | |||
487 | 496 | ||
488 | hcd->uses_new_polling = 1; | 497 | hcd->uses_new_polling = 1; |
489 | 498 | ||
490 | uhci->fsbr = 0; | ||
491 | uhci->fsbrtimeout = 0; | ||
492 | |||
493 | spin_lock_init(&uhci->lock); | 499 | spin_lock_init(&uhci->lock); |
494 | 500 | setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout, | |
495 | INIT_LIST_HEAD(&uhci->td_remove_list); | 501 | (unsigned long) uhci); |
496 | INIT_LIST_HEAD(&uhci->idle_qh_list); | 502 | INIT_LIST_HEAD(&uhci->idle_qh_list); |
497 | |||
498 | init_waitqueue_head(&uhci->waitqh); | 503 | init_waitqueue_head(&uhci->waitqh); |
499 | 504 | ||
500 | if (DEBUG_CONFIGURED) { | 505 | if (DEBUG_CONFIGURED) { |
@@ -665,11 +670,12 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
665 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 670 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
666 | 671 | ||
667 | spin_lock_irq(&uhci->lock); | 672 | spin_lock_irq(&uhci->lock); |
668 | if (!uhci->hc_inaccessible) | 673 | if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead) |
669 | hc_died(uhci); | 674 | uhci_hc_died(uhci); |
670 | uhci_scan_schedule(uhci, NULL); | 675 | uhci_scan_schedule(uhci, NULL); |
671 | spin_unlock_irq(&uhci->lock); | 676 | spin_unlock_irq(&uhci->lock); |
672 | 677 | ||
678 | del_timer_sync(&uhci->fsbr_timer); | ||
673 | release_uhci(uhci); | 679 | release_uhci(uhci); |
674 | } | 680 | } |
675 | 681 | ||
@@ -677,12 +683,15 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
677 | static int uhci_rh_suspend(struct usb_hcd *hcd) | 683 | static int uhci_rh_suspend(struct usb_hcd *hcd) |
678 | { | 684 | { |
679 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 685 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
686 | int rc = 0; | ||
680 | 687 | ||
681 | spin_lock_irq(&uhci->lock); | 688 | spin_lock_irq(&uhci->lock); |
682 | if (!uhci->hc_inaccessible) /* Not dead */ | 689 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) |
690 | rc = -ESHUTDOWN; | ||
691 | else if (!uhci->dead) | ||
683 | suspend_rh(uhci, UHCI_RH_SUSPENDED); | 692 | suspend_rh(uhci, UHCI_RH_SUSPENDED); |
684 | spin_unlock_irq(&uhci->lock); | 693 | spin_unlock_irq(&uhci->lock); |
685 | return 0; | 694 | return rc; |
686 | } | 695 | } |
687 | 696 | ||
688 | static int uhci_rh_resume(struct usb_hcd *hcd) | 697 | static int uhci_rh_resume(struct usb_hcd *hcd) |
@@ -691,13 +700,10 @@ static int uhci_rh_resume(struct usb_hcd *hcd) | |||
691 | int rc = 0; | 700 | int rc = 0; |
692 | 701 | ||
693 | spin_lock_irq(&uhci->lock); | 702 | spin_lock_irq(&uhci->lock); |
694 | if (uhci->hc_inaccessible) { | 703 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { |
695 | if (uhci->rh_state == UHCI_RH_SUSPENDED) { | 704 | dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n"); |
696 | dev_warn(uhci_dev(uhci), "HC isn't running!\n"); | 705 | rc = -ESHUTDOWN; |
697 | rc = -ENODEV; | 706 | } else if (!uhci->dead) |
698 | } | ||
699 | /* Otherwise the HC is dead */ | ||
700 | } else | ||
701 | wakeup_rh(uhci); | 707 | wakeup_rh(uhci); |
702 | spin_unlock_irq(&uhci->lock); | 708 | spin_unlock_irq(&uhci->lock); |
703 | return rc; | 709 | return rc; |
@@ -711,8 +717,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
711 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); | 717 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); |
712 | 718 | ||
713 | spin_lock_irq(&uhci->lock); | 719 | spin_lock_irq(&uhci->lock); |
714 | if (uhci->hc_inaccessible) /* Dead or already suspended */ | 720 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) |
715 | goto done; | 721 | goto done_okay; /* Already suspended or dead */ |
716 | 722 | ||
717 | if (uhci->rh_state > UHCI_RH_SUSPENDED) { | 723 | if (uhci->rh_state > UHCI_RH_SUSPENDED) { |
718 | dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); | 724 | dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); |
@@ -725,12 +731,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
725 | */ | 731 | */ |
726 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); | 732 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); |
727 | mb(); | 733 | mb(); |
728 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
729 | uhci->hc_inaccessible = 1; | ||
730 | hcd->poll_rh = 0; | 734 | hcd->poll_rh = 0; |
731 | 735 | ||
732 | /* FIXME: Enable non-PME# remote wakeup? */ | 736 | /* FIXME: Enable non-PME# remote wakeup? */ |
733 | 737 | ||
738 | done_okay: | ||
739 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
734 | done: | 740 | done: |
735 | spin_unlock_irq(&uhci->lock); | 741 | spin_unlock_irq(&uhci->lock); |
736 | return rc; | 742 | return rc; |
@@ -743,24 +749,22 @@ static int uhci_resume(struct usb_hcd *hcd) | |||
743 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); | 749 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); |
744 | 750 | ||
745 | /* Since we aren't in D3 any more, it's safe to set this flag | 751 | /* Since we aren't in D3 any more, it's safe to set this flag |
746 | * even if the controller was dead. It might not even be dead | 752 | * even if the controller was dead. |
747 | * any more, if the firmware or quirks code has reset it. | ||
748 | */ | 753 | */ |
749 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 754 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
750 | mb(); | 755 | mb(); |
751 | 756 | ||
752 | if (uhci->rh_state == UHCI_RH_RESET) /* Dead */ | ||
753 | return 0; | ||
754 | spin_lock_irq(&uhci->lock); | 757 | spin_lock_irq(&uhci->lock); |
755 | 758 | ||
756 | /* FIXME: Disable non-PME# remote wakeup? */ | 759 | /* FIXME: Disable non-PME# remote wakeup? */ |
757 | 760 | ||
758 | uhci->hc_inaccessible = 0; | 761 | /* The firmware or a boot kernel may have changed the controller |
759 | 762 | * settings during a system wakeup. Check it and reconfigure | |
760 | /* The BIOS may have changed the controller settings during a | 763 | * to avoid problems. |
761 | * system wakeup. Check it and reconfigure to avoid problems. | ||
762 | */ | 764 | */ |
763 | check_and_reset_hc(uhci); | 765 | check_and_reset_hc(uhci); |
766 | |||
767 | /* If the controller was dead before, it's back alive now */ | ||
764 | configure_hc(uhci); | 768 | configure_hc(uhci); |
765 | 769 | ||
766 | if (uhci->rh_state == UHCI_RH_RESET) { | 770 | if (uhci->rh_state == UHCI_RH_RESET) { |
@@ -810,18 +814,15 @@ done: | |||
810 | static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) | 814 | static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) |
811 | { | 815 | { |
812 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 816 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
813 | unsigned long flags; | 817 | unsigned frame_number; |
814 | int is_stopped; | 818 | unsigned delta; |
815 | int frame_number; | ||
816 | 819 | ||
817 | /* Minimize latency by avoiding the spinlock */ | 820 | /* Minimize latency by avoiding the spinlock */ |
818 | local_irq_save(flags); | 821 | frame_number = uhci->frame_number; |
819 | is_stopped = uhci->is_stopped; | 822 | barrier(); |
820 | smp_rmb(); | 823 | delta = (inw(uhci->io_addr + USBFRNUM) - frame_number) & |
821 | frame_number = (is_stopped ? uhci->frame_number : | 824 | (UHCI_NUMFRAMES - 1); |
822 | inw(uhci->io_addr + USBFRNUM)); | 825 | return frame_number + delta; |
823 | local_irq_restore(flags); | ||
824 | return frame_number; | ||
825 | } | 826 | } |
826 | 827 | ||
827 | static const char hcd_name[] = "uhci_hcd"; | 828 | static const char hcd_name[] = "uhci_hcd"; |
@@ -836,7 +837,7 @@ static const struct hc_driver uhci_driver = { | |||
836 | .flags = HCD_USB11, | 837 | .flags = HCD_USB11, |
837 | 838 | ||
838 | /* Basic lifecycle operations */ | 839 | /* Basic lifecycle operations */ |
839 | .reset = uhci_reset, | 840 | .reset = uhci_init, |
840 | .start = uhci_start, | 841 | .start = uhci_start, |
841 | #ifdef CONFIG_PM | 842 | #ifdef CONFIG_PM |
842 | .suspend = uhci_suspend, | 843 | .suspend = uhci_suspend, |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index d5c8f4d92823..108e3de2dc26 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -84,6 +84,13 @@ | |||
84 | #define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames | 84 | #define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames |
85 | * can be scheduled */ | 85 | * can be scheduled */ |
86 | 86 | ||
87 | /* When no queues need Full-Speed Bandwidth Reclamation, | ||
88 | * delay this long before turning FSBR off */ | ||
89 | #define FSBR_OFF_DELAY msecs_to_jiffies(10) | ||
90 | |||
91 | /* If a queue hasn't advanced after this much time, assume it is stuck */ | ||
92 | #define QH_WAIT_TIMEOUT msecs_to_jiffies(200) | ||
93 | |||
87 | 94 | ||
88 | /* | 95 | /* |
89 | * Queue Headers | 96 | * Queue Headers |
@@ -121,21 +128,31 @@ struct uhci_qh { | |||
121 | __le32 element; /* Queue element (TD) pointer */ | 128 | __le32 element; /* Queue element (TD) pointer */ |
122 | 129 | ||
123 | /* Software fields */ | 130 | /* Software fields */ |
124 | dma_addr_t dma_handle; | ||
125 | |||
126 | struct list_head node; /* Node in the list of QHs */ | 131 | struct list_head node; /* Node in the list of QHs */ |
127 | struct usb_host_endpoint *hep; /* Endpoint information */ | 132 | struct usb_host_endpoint *hep; /* Endpoint information */ |
128 | struct usb_device *udev; | 133 | struct usb_device *udev; |
129 | struct list_head queue; /* Queue of urbps for this QH */ | 134 | struct list_head queue; /* Queue of urbps for this QH */ |
130 | struct uhci_qh *skel; /* Skeleton for this QH */ | 135 | struct uhci_qh *skel; /* Skeleton for this QH */ |
131 | struct uhci_td *dummy_td; /* Dummy TD to end the queue */ | 136 | struct uhci_td *dummy_td; /* Dummy TD to end the queue */ |
137 | struct uhci_td *post_td; /* Last TD completed */ | ||
132 | 138 | ||
139 | struct usb_iso_packet_descriptor *iso_packet_desc; | ||
140 | /* Next urb->iso_frame_desc entry */ | ||
141 | unsigned long advance_jiffies; /* Time of last queue advance */ | ||
133 | unsigned int unlink_frame; /* When the QH was unlinked */ | 142 | unsigned int unlink_frame; /* When the QH was unlinked */ |
143 | unsigned int period; /* For Interrupt and Isochronous QHs */ | ||
144 | unsigned int iso_frame; /* Frame # for iso_packet_desc */ | ||
145 | int iso_status; /* Status for Isochronous URBs */ | ||
146 | |||
134 | int state; /* QH_STATE_xxx; see above */ | 147 | int state; /* QH_STATE_xxx; see above */ |
148 | int type; /* Queue type (control, bulk, etc) */ | ||
149 | |||
150 | dma_addr_t dma_handle; | ||
135 | 151 | ||
136 | unsigned int initial_toggle:1; /* Endpoint's current toggle value */ | 152 | unsigned int initial_toggle:1; /* Endpoint's current toggle value */ |
137 | unsigned int needs_fixup:1; /* Must fix the TD toggle values */ | 153 | unsigned int needs_fixup:1; /* Must fix the TD toggle values */ |
138 | unsigned int is_stopped:1; /* Queue was stopped by an error */ | 154 | unsigned int is_stopped:1; /* Queue was stopped by error/unlink */ |
155 | unsigned int wait_expired:1; /* QH_WAIT_TIMEOUT has expired */ | ||
139 | } __attribute__((aligned(16))); | 156 | } __attribute__((aligned(16))); |
140 | 157 | ||
141 | /* | 158 | /* |
@@ -226,7 +243,6 @@ struct uhci_td { | |||
226 | dma_addr_t dma_handle; | 243 | dma_addr_t dma_handle; |
227 | 244 | ||
228 | struct list_head list; | 245 | struct list_head list; |
229 | struct list_head remove_list; | ||
230 | 246 | ||
231 | int frame; /* for iso: what frame? */ | 247 | int frame; /* for iso: what frame? */ |
232 | struct list_head fl_list; | 248 | struct list_head fl_list; |
@@ -305,38 +321,8 @@ static inline u32 td_status(struct uhci_td *td) { | |||
305 | #define skel_bulk_qh skelqh[12] | 321 | #define skel_bulk_qh skelqh[12] |
306 | #define skel_term_qh skelqh[13] | 322 | #define skel_term_qh skelqh[13] |
307 | 323 | ||
308 | /* | 324 | /* Find the skelqh entry corresponding to an interval exponent */ |
309 | * Search tree for determining where <interval> fits in the skelqh[] | 325 | #define UHCI_SKEL_INDEX(exponent) (9 - exponent) |
310 | * skeleton. | ||
311 | * | ||
312 | * An interrupt request should be placed into the slowest skelqh[] | ||
313 | * which meets the interval/period/frequency requirement. | ||
314 | * An interrupt request is allowed to be faster than <interval> but not slower. | ||
315 | * | ||
316 | * For a given <interval>, this function returns the appropriate/matching | ||
317 | * skelqh[] index value. | ||
318 | */ | ||
319 | static inline int __interval_to_skel(int interval) | ||
320 | { | ||
321 | if (interval < 16) { | ||
322 | if (interval < 4) { | ||
323 | if (interval < 2) | ||
324 | return 9; /* int1 for 0-1 ms */ | ||
325 | return 8; /* int2 for 2-3 ms */ | ||
326 | } | ||
327 | if (interval < 8) | ||
328 | return 7; /* int4 for 4-7 ms */ | ||
329 | return 6; /* int8 for 8-15 ms */ | ||
330 | } | ||
331 | if (interval < 64) { | ||
332 | if (interval < 32) | ||
333 | return 5; /* int16 for 16-31 ms */ | ||
334 | return 4; /* int32 for 32-63 ms */ | ||
335 | } | ||
336 | if (interval < 128) | ||
337 | return 3; /* int64 for 64-127 ms */ | ||
338 | return 2; /* int128 for 128-255 ms (Max.) */ | ||
339 | } | ||
340 | 326 | ||
341 | 327 | ||
342 | /* | 328 | /* |
@@ -396,32 +382,32 @@ struct uhci_hcd { | |||
396 | __le32 *frame; | 382 | __le32 *frame; |
397 | void **frame_cpu; /* CPU's frame list */ | 383 | void **frame_cpu; /* CPU's frame list */ |
398 | 384 | ||
399 | int fsbr; /* Full-speed bandwidth reclamation */ | ||
400 | unsigned long fsbrtimeout; /* FSBR delay */ | ||
401 | |||
402 | enum uhci_rh_state rh_state; | 385 | enum uhci_rh_state rh_state; |
403 | unsigned long auto_stop_time; /* When to AUTO_STOP */ | 386 | unsigned long auto_stop_time; /* When to AUTO_STOP */ |
404 | 387 | ||
405 | unsigned int frame_number; /* As of last check */ | 388 | unsigned int frame_number; /* As of last check */ |
406 | unsigned int is_stopped; | 389 | unsigned int is_stopped; |
407 | #define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ | 390 | #define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ |
391 | unsigned int last_iso_frame; /* Frame of last scan */ | ||
392 | unsigned int cur_iso_frame; /* Frame for current scan */ | ||
408 | 393 | ||
409 | unsigned int scan_in_progress:1; /* Schedule scan is running */ | 394 | unsigned int scan_in_progress:1; /* Schedule scan is running */ |
410 | unsigned int need_rescan:1; /* Redo the schedule scan */ | 395 | unsigned int need_rescan:1; /* Redo the schedule scan */ |
411 | unsigned int hc_inaccessible:1; /* HC is suspended or dead */ | 396 | unsigned int dead:1; /* Controller has died */ |
412 | unsigned int working_RD:1; /* Suspended root hub doesn't | 397 | unsigned int working_RD:1; /* Suspended root hub doesn't |
413 | need to be polled */ | 398 | need to be polled */ |
414 | unsigned int is_initialized:1; /* Data structure is usable */ | 399 | unsigned int is_initialized:1; /* Data structure is usable */ |
400 | unsigned int fsbr_is_on:1; /* FSBR is turned on */ | ||
401 | unsigned int fsbr_is_wanted:1; /* Does any URB want FSBR? */ | ||
402 | unsigned int fsbr_expiring:1; /* FSBR is timing out */ | ||
403 | |||
404 | struct timer_list fsbr_timer; /* For turning off FBSR */ | ||
415 | 405 | ||
416 | /* Support for port suspend/resume/reset */ | 406 | /* Support for port suspend/resume/reset */ |
417 | unsigned long port_c_suspend; /* Bit-arrays of ports */ | 407 | unsigned long port_c_suspend; /* Bit-arrays of ports */ |
418 | unsigned long resuming_ports; | 408 | unsigned long resuming_ports; |
419 | unsigned long ports_timeout; /* Time to stop signalling */ | 409 | unsigned long ports_timeout; /* Time to stop signalling */ |
420 | 410 | ||
421 | /* List of TDs that are done, but waiting to be freed (race) */ | ||
422 | struct list_head td_remove_list; | ||
423 | unsigned int td_remove_age; /* Age in frames */ | ||
424 | |||
425 | struct list_head idle_qh_list; /* Where the idle QHs live */ | 411 | struct list_head idle_qh_list; /* Where the idle QHs live */ |
426 | 412 | ||
427 | int rh_numports; /* Number of root-hub ports */ | 413 | int rh_numports; /* Number of root-hub ports */ |
@@ -442,6 +428,9 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci) | |||
442 | 428 | ||
443 | #define uhci_dev(u) (uhci_to_hcd(u)->self.controller) | 429 | #define uhci_dev(u) (uhci_to_hcd(u)->self.controller) |
444 | 430 | ||
431 | /* Utility macro for comparing frame numbers */ | ||
432 | #define uhci_frame_before_eq(f1, f2) (0 <= (int) ((f2) - (f1))) | ||
433 | |||
445 | 434 | ||
446 | /* | 435 | /* |
447 | * Private per-URB data | 436 | * Private per-URB data |
@@ -454,9 +443,7 @@ struct urb_priv { | |||
454 | struct uhci_qh *qh; /* QH for this URB */ | 443 | struct uhci_qh *qh; /* QH for this URB */ |
455 | struct list_head td_list; | 444 | struct list_head td_list; |
456 | 445 | ||
457 | unsigned fsbr : 1; /* URB turned on FSBR */ | 446 | unsigned fsbr:1; /* URB wants FSBR */ |
458 | unsigned short_transfer : 1; /* URB got a short transfer, no | ||
459 | * need to rescan */ | ||
460 | }; | 447 | }; |
461 | 448 | ||
462 | 449 | ||
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index c8451d9578f1..c545ef92fe29 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
@@ -171,9 +171,8 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
171 | spin_lock_irqsave(&uhci->lock, flags); | 171 | spin_lock_irqsave(&uhci->lock, flags); |
172 | 172 | ||
173 | uhci_scan_schedule(uhci, NULL); | 173 | uhci_scan_schedule(uhci, NULL); |
174 | if (uhci->hc_inaccessible) | 174 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) |
175 | goto done; | 175 | goto done; |
176 | check_fsbr(uhci); | ||
177 | uhci_check_ports(uhci); | 176 | uhci_check_ports(uhci); |
178 | 177 | ||
179 | status = get_hub_status_data(uhci, buf); | 178 | status = get_hub_status_data(uhci, buf); |
@@ -228,7 +227,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
228 | u16 wPortChange, wPortStatus; | 227 | u16 wPortChange, wPortStatus; |
229 | unsigned long flags; | 228 | unsigned long flags; |
230 | 229 | ||
231 | if (uhci->hc_inaccessible) | 230 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) |
232 | return -ETIMEDOUT; | 231 | return -ETIMEDOUT; |
233 | 232 | ||
234 | spin_lock_irqsave(&uhci->lock, flags); | 233 | spin_lock_irqsave(&uhci->lock, flags); |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index a06d84c19e13..c9d72ac0a1d7 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -13,10 +13,9 @@ | |||
13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface | 13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface |
14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). | 14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). |
15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) | 15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) |
16 | * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu | 16 | * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu |
17 | */ | 17 | */ |
18 | 18 | ||
19 | static void uhci_free_pending_tds(struct uhci_hcd *uhci); | ||
20 | 19 | ||
21 | /* | 20 | /* |
22 | * Technically, updating td->status here is a race, but it's not really a | 21 | * Technically, updating td->status here is a race, but it's not really a |
@@ -38,6 +37,60 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) | |||
38 | uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC); | 37 | uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC); |
39 | } | 38 | } |
40 | 39 | ||
40 | |||
41 | /* | ||
42 | * Full-Speed Bandwidth Reclamation (FSBR). | ||
43 | * We turn on FSBR whenever a queue that wants it is advancing, | ||
44 | * and leave it on for a short time thereafter. | ||
45 | */ | ||
46 | static void uhci_fsbr_on(struct uhci_hcd *uhci) | ||
47 | { | ||
48 | uhci->fsbr_is_on = 1; | ||
49 | uhci->skel_term_qh->link = cpu_to_le32( | ||
50 | uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; | ||
51 | } | ||
52 | |||
53 | static void uhci_fsbr_off(struct uhci_hcd *uhci) | ||
54 | { | ||
55 | uhci->fsbr_is_on = 0; | ||
56 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | ||
57 | } | ||
58 | |||
59 | static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb) | ||
60 | { | ||
61 | struct urb_priv *urbp = urb->hcpriv; | ||
62 | |||
63 | if (!(urb->transfer_flags & URB_NO_FSBR)) | ||
64 | urbp->fsbr = 1; | ||
65 | } | ||
66 | |||
67 | static void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp) | ||
68 | { | ||
69 | if (urbp->fsbr) { | ||
70 | uhci->fsbr_is_wanted = 1; | ||
71 | if (!uhci->fsbr_is_on) | ||
72 | uhci_fsbr_on(uhci); | ||
73 | else if (uhci->fsbr_expiring) { | ||
74 | uhci->fsbr_expiring = 0; | ||
75 | del_timer(&uhci->fsbr_timer); | ||
76 | } | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static void uhci_fsbr_timeout(unsigned long _uhci) | ||
81 | { | ||
82 | struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci; | ||
83 | unsigned long flags; | ||
84 | |||
85 | spin_lock_irqsave(&uhci->lock, flags); | ||
86 | if (uhci->fsbr_expiring) { | ||
87 | uhci->fsbr_expiring = 0; | ||
88 | uhci_fsbr_off(uhci); | ||
89 | } | ||
90 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
91 | } | ||
92 | |||
93 | |||
41 | static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) | 94 | static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) |
42 | { | 95 | { |
43 | dma_addr_t dma_handle; | 96 | dma_addr_t dma_handle; |
@@ -51,7 +104,6 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) | |||
51 | td->frame = -1; | 104 | td->frame = -1; |
52 | 105 | ||
53 | INIT_LIST_HEAD(&td->list); | 106 | INIT_LIST_HEAD(&td->list); |
54 | INIT_LIST_HEAD(&td->remove_list); | ||
55 | INIT_LIST_HEAD(&td->fl_list); | 107 | INIT_LIST_HEAD(&td->fl_list); |
56 | 108 | ||
57 | return td; | 109 | return td; |
@@ -61,8 +113,6 @@ static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) | |||
61 | { | 113 | { |
62 | if (!list_empty(&td->list)) | 114 | if (!list_empty(&td->list)) |
63 | dev_warn(uhci_dev(uhci), "td %p still in list!\n", td); | 115 | dev_warn(uhci_dev(uhci), "td %p still in list!\n", td); |
64 | if (!list_empty(&td->remove_list)) | ||
65 | dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td); | ||
66 | if (!list_empty(&td->fl_list)) | 116 | if (!list_empty(&td->fl_list)) |
67 | dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); | 117 | dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); |
68 | 118 | ||
@@ -77,6 +127,16 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status, | |||
77 | td->buffer = cpu_to_le32(buffer); | 127 | td->buffer = cpu_to_le32(buffer); |
78 | } | 128 | } |
79 | 129 | ||
130 | static void uhci_add_td_to_urbp(struct uhci_td *td, struct urb_priv *urbp) | ||
131 | { | ||
132 | list_add_tail(&td->list, &urbp->td_list); | ||
133 | } | ||
134 | |||
135 | static void uhci_remove_td_from_urbp(struct uhci_td *td) | ||
136 | { | ||
137 | list_del_init(&td->list); | ||
138 | } | ||
139 | |||
80 | /* | 140 | /* |
81 | * We insert Isochronous URBs directly into the frame list at the beginning | 141 | * We insert Isochronous URBs directly into the frame list at the beginning |
82 | */ | 142 | */ |
@@ -138,6 +198,24 @@ static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci, | |||
138 | td->frame = -1; | 198 | td->frame = -1; |
139 | } | 199 | } |
140 | 200 | ||
201 | static inline void uhci_remove_tds_from_frame(struct uhci_hcd *uhci, | ||
202 | unsigned int framenum) | ||
203 | { | ||
204 | struct uhci_td *ftd, *ltd; | ||
205 | |||
206 | framenum &= (UHCI_NUMFRAMES - 1); | ||
207 | |||
208 | ftd = uhci->frame_cpu[framenum]; | ||
209 | if (ftd) { | ||
210 | ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); | ||
211 | uhci->frame[framenum] = ltd->link; | ||
212 | uhci->frame_cpu[framenum] = NULL; | ||
213 | |||
214 | while (!list_empty(&ftd->fl_list)) | ||
215 | list_del_init(ftd->fl_list.prev); | ||
216 | } | ||
217 | } | ||
218 | |||
141 | /* | 219 | /* |
142 | * Remove all the TDs for an Isochronous URB from the frame list | 220 | * Remove all the TDs for an Isochronous URB from the frame list |
143 | */ | 221 | */ |
@@ -148,7 +226,6 @@ static void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb) | |||
148 | 226 | ||
149 | list_for_each_entry(td, &urbp->td_list, list) | 227 | list_for_each_entry(td, &urbp->td_list, list) |
150 | uhci_remove_td_from_frame_list(uhci, td); | 228 | uhci_remove_td_from_frame_list(uhci, td); |
151 | wmb(); | ||
152 | } | 229 | } |
153 | 230 | ||
154 | static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, | 231 | static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, |
@@ -161,6 +238,7 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, | |||
161 | if (!qh) | 238 | if (!qh) |
162 | return NULL; | 239 | return NULL; |
163 | 240 | ||
241 | memset(qh, 0, sizeof(*qh)); | ||
164 | qh->dma_handle = dma_handle; | 242 | qh->dma_handle = dma_handle; |
165 | 243 | ||
166 | qh->element = UHCI_PTR_TERM; | 244 | qh->element = UHCI_PTR_TERM; |
@@ -179,10 +257,11 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, | |||
179 | qh->hep = hep; | 257 | qh->hep = hep; |
180 | qh->udev = udev; | 258 | qh->udev = udev; |
181 | hep->hcpriv = qh; | 259 | hep->hcpriv = qh; |
260 | qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | ||
182 | 261 | ||
183 | } else { /* Skeleton QH */ | 262 | } else { /* Skeleton QH */ |
184 | qh->state = QH_STATE_ACTIVE; | 263 | qh->state = QH_STATE_ACTIVE; |
185 | qh->udev = NULL; | 264 | qh->type = -1; |
186 | } | 265 | } |
187 | return qh; | 266 | return qh; |
188 | } | 267 | } |
@@ -202,35 +281,64 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
202 | } | 281 | } |
203 | 282 | ||
204 | /* | 283 | /* |
205 | * When the currently executing URB is dequeued, save its current toggle value | 284 | * When a queue is stopped and a dequeued URB is given back, adjust |
285 | * the previous TD link (if the URB isn't first on the queue) or | ||
286 | * save its toggle value (if it is first and is currently executing). | ||
287 | * | ||
288 | * Returns 0 if the URB should not yet be given back, 1 otherwise. | ||
206 | */ | 289 | */ |
207 | static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb) | 290 | static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh, |
291 | struct urb *urb) | ||
208 | { | 292 | { |
209 | struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; | 293 | struct urb_priv *urbp = urb->hcpriv; |
210 | struct uhci_td *td; | 294 | struct uhci_td *td; |
295 | int ret = 1; | ||
296 | |||
297 | /* Isochronous pipes don't use toggles and their TD link pointers | ||
298 | * get adjusted during uhci_urb_dequeue(). But since their queues | ||
299 | * cannot truly be stopped, we have to watch out for dequeues | ||
300 | * occurring after the nominal unlink frame. */ | ||
301 | if (qh->type == USB_ENDPOINT_XFER_ISOC) { | ||
302 | ret = (uhci->frame_number + uhci->is_stopped != | ||
303 | qh->unlink_frame); | ||
304 | goto done; | ||
305 | } | ||
306 | |||
307 | /* If the URB isn't first on its queue, adjust the link pointer | ||
308 | * of the last TD in the previous URB. The toggle doesn't need | ||
309 | * to be saved since this URB can't be executing yet. */ | ||
310 | if (qh->queue.next != &urbp->node) { | ||
311 | struct urb_priv *purbp; | ||
312 | struct uhci_td *ptd; | ||
313 | |||
314 | purbp = list_entry(urbp->node.prev, struct urb_priv, node); | ||
315 | WARN_ON(list_empty(&purbp->td_list)); | ||
316 | ptd = list_entry(purbp->td_list.prev, struct uhci_td, | ||
317 | list); | ||
318 | td = list_entry(urbp->td_list.prev, struct uhci_td, | ||
319 | list); | ||
320 | ptd->link = td->link; | ||
321 | goto done; | ||
322 | } | ||
211 | 323 | ||
212 | /* If the QH element pointer is UHCI_PTR_TERM then then currently | 324 | /* If the QH element pointer is UHCI_PTR_TERM then then currently |
213 | * executing URB has already been unlinked, so this one isn't it. */ | 325 | * executing URB has already been unlinked, so this one isn't it. */ |
214 | if (qh_element(qh) == UHCI_PTR_TERM || | 326 | if (qh_element(qh) == UHCI_PTR_TERM) |
215 | qh->queue.next != &urbp->node) | 327 | goto done; |
216 | return; | ||
217 | qh->element = UHCI_PTR_TERM; | 328 | qh->element = UHCI_PTR_TERM; |
218 | 329 | ||
219 | /* Only bulk and interrupt pipes have to worry about toggles */ | 330 | /* Control pipes have to worry about toggles */ |
220 | if (!(usb_pipetype(urb->pipe) == PIPE_BULK || | 331 | if (qh->type == USB_ENDPOINT_XFER_CONTROL) |
221 | usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) | 332 | goto done; |
222 | return; | ||
223 | 333 | ||
224 | /* Find the first active TD; that's the device's toggle state */ | 334 | /* Save the next toggle value */ |
225 | list_for_each_entry(td, &urbp->td_list, list) { | 335 | WARN_ON(list_empty(&urbp->td_list)); |
226 | if (td_status(td) & TD_CTRL_ACTIVE) { | 336 | td = list_entry(urbp->td_list.next, struct uhci_td, list); |
227 | qh->needs_fixup = 1; | 337 | qh->needs_fixup = 1; |
228 | qh->initial_toggle = uhci_toggle(td_token(td)); | 338 | qh->initial_toggle = uhci_toggle(td_token(td)); |
229 | return; | ||
230 | } | ||
231 | } | ||
232 | 339 | ||
233 | WARN_ON(1); | 340 | done: |
341 | return ret; | ||
234 | } | 342 | } |
235 | 343 | ||
236 | /* | 344 | /* |
@@ -305,6 +413,10 @@ static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
305 | qh->element = cpu_to_le32(td->dma_handle); | 413 | qh->element = cpu_to_le32(td->dma_handle); |
306 | } | 414 | } |
307 | 415 | ||
416 | /* Treat the queue as if it has just advanced */ | ||
417 | qh->wait_expired = 0; | ||
418 | qh->advance_jiffies = jiffies; | ||
419 | |||
308 | if (qh->state == QH_STATE_ACTIVE) | 420 | if (qh->state == QH_STATE_ACTIVE) |
309 | return; | 421 | return; |
310 | qh->state = QH_STATE_ACTIVE; | 422 | qh->state = QH_STATE_ACTIVE; |
@@ -370,6 +482,12 @@ static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
370 | list_move(&qh->node, &uhci->idle_qh_list); | 482 | list_move(&qh->node, &uhci->idle_qh_list); |
371 | qh->state = QH_STATE_IDLE; | 483 | qh->state = QH_STATE_IDLE; |
372 | 484 | ||
485 | /* Now that the QH is idle, its post_td isn't being used */ | ||
486 | if (qh->post_td) { | ||
487 | uhci_free_td(uhci, qh->post_td); | ||
488 | qh->post_td = NULL; | ||
489 | } | ||
490 | |||
373 | /* If anyone is waiting for a QH to become idle, wake them up */ | 491 | /* If anyone is waiting for a QH to become idle, wake them up */ |
374 | if (uhci->num_waiting) | 492 | if (uhci->num_waiting) |
375 | wake_up_all(&uhci->waitqh); | 493 | wake_up_all(&uhci->waitqh); |
@@ -395,21 +513,6 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, | |||
395 | return urbp; | 513 | return urbp; |
396 | } | 514 | } |
397 | 515 | ||
398 | static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td) | ||
399 | { | ||
400 | struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; | ||
401 | |||
402 | list_add_tail(&td->list, &urbp->td_list); | ||
403 | } | ||
404 | |||
405 | static void uhci_remove_td_from_urb(struct uhci_td *td) | ||
406 | { | ||
407 | if (list_empty(&td->list)) | ||
408 | return; | ||
409 | |||
410 | list_del_init(&td->list); | ||
411 | } | ||
412 | |||
413 | static void uhci_free_urb_priv(struct uhci_hcd *uhci, | 516 | static void uhci_free_urb_priv(struct uhci_hcd *uhci, |
414 | struct urb_priv *urbp) | 517 | struct urb_priv *urbp) |
415 | { | 518 | { |
@@ -419,48 +522,15 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci, | |||
419 | dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n", | 522 | dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n", |
420 | urbp->urb); | 523 | urbp->urb); |
421 | 524 | ||
422 | uhci_get_current_frame_number(uhci); | ||
423 | if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) { | ||
424 | uhci_free_pending_tds(uhci); | ||
425 | uhci->td_remove_age = uhci->frame_number; | ||
426 | } | ||
427 | |||
428 | /* Check to see if the remove list is empty. Set the IOC bit */ | ||
429 | /* to force an interrupt so we can remove the TDs. */ | ||
430 | if (list_empty(&uhci->td_remove_list)) | ||
431 | uhci_set_next_interrupt(uhci); | ||
432 | |||
433 | list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { | 525 | list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { |
434 | uhci_remove_td_from_urb(td); | 526 | uhci_remove_td_from_urbp(td); |
435 | list_add(&td->remove_list, &uhci->td_remove_list); | 527 | uhci_free_td(uhci, td); |
436 | } | 528 | } |
437 | 529 | ||
438 | urbp->urb->hcpriv = NULL; | 530 | urbp->urb->hcpriv = NULL; |
439 | kmem_cache_free(uhci_up_cachep, urbp); | 531 | kmem_cache_free(uhci_up_cachep, urbp); |
440 | } | 532 | } |
441 | 533 | ||
442 | static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb) | ||
443 | { | ||
444 | struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; | ||
445 | |||
446 | if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) { | ||
447 | urbp->fsbr = 1; | ||
448 | if (!uhci->fsbr++ && !uhci->fsbrtimeout) | ||
449 | uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb) | ||
454 | { | ||
455 | struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; | ||
456 | |||
457 | if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) { | ||
458 | urbp->fsbr = 0; | ||
459 | if (!--uhci->fsbr) | ||
460 | uhci->fsbrtimeout = jiffies + FSBR_DELAY; | ||
461 | } | ||
462 | } | ||
463 | |||
464 | /* | 534 | /* |
465 | * Map status to standard result codes | 535 | * Map status to standard result codes |
466 | * | 536 | * |
@@ -487,7 +557,6 @@ static int uhci_map_status(int status, int dir_out) | |||
487 | return -ENOSR; | 557 | return -ENOSR; |
488 | if (status & TD_CTRL_STALLED) /* Stalled */ | 558 | if (status & TD_CTRL_STALLED) /* Stalled */ |
489 | return -EPIPE; | 559 | return -EPIPE; |
490 | WARN_ON(status & TD_CTRL_ACTIVE); /* Active */ | ||
491 | return 0; | 560 | return 0; |
492 | } | 561 | } |
493 | 562 | ||
@@ -503,6 +572,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
503 | int len = urb->transfer_buffer_length; | 572 | int len = urb->transfer_buffer_length; |
504 | dma_addr_t data = urb->transfer_dma; | 573 | dma_addr_t data = urb->transfer_dma; |
505 | __le32 *plink; | 574 | __le32 *plink; |
575 | struct urb_priv *urbp = urb->hcpriv; | ||
506 | 576 | ||
507 | /* The "pipe" thing contains the destination in bits 8--18 */ | 577 | /* The "pipe" thing contains the destination in bits 8--18 */ |
508 | destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; | 578 | destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; |
@@ -516,7 +586,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
516 | * Build the TD for the control request setup packet | 586 | * Build the TD for the control request setup packet |
517 | */ | 587 | */ |
518 | td = qh->dummy_td; | 588 | td = qh->dummy_td; |
519 | uhci_add_td_to_urb(urb, td); | 589 | uhci_add_td_to_urbp(td, urbp); |
520 | uhci_fill_td(td, status, destination | uhci_explen(8), | 590 | uhci_fill_td(td, status, destination | uhci_explen(8), |
521 | urb->setup_dma); | 591 | urb->setup_dma); |
522 | plink = &td->link; | 592 | plink = &td->link; |
@@ -548,7 +618,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
548 | /* Alternate Data0/1 (start with Data1) */ | 618 | /* Alternate Data0/1 (start with Data1) */ |
549 | destination ^= TD_TOKEN_TOGGLE; | 619 | destination ^= TD_TOKEN_TOGGLE; |
550 | 620 | ||
551 | uhci_add_td_to_urb(urb, td); | 621 | uhci_add_td_to_urbp(td, urbp); |
552 | uhci_fill_td(td, status, destination | uhci_explen(pktsze), | 622 | uhci_fill_td(td, status, destination | uhci_explen(pktsze), |
553 | data); | 623 | data); |
554 | plink = &td->link; | 624 | plink = &td->link; |
@@ -579,7 +649,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
579 | 649 | ||
580 | status &= ~TD_CTRL_SPD; | 650 | status &= ~TD_CTRL_SPD; |
581 | 651 | ||
582 | uhci_add_td_to_urb(urb, td); | 652 | uhci_add_td_to_urbp(td, urbp); |
583 | uhci_fill_td(td, status | TD_CTRL_IOC, | 653 | uhci_fill_td(td, status | TD_CTRL_IOC, |
584 | destination | uhci_explen(0), 0); | 654 | destination | uhci_explen(0), 0); |
585 | plink = &td->link; | 655 | plink = &td->link; |
@@ -606,145 +676,19 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
606 | qh->skel = uhci->skel_ls_control_qh; | 676 | qh->skel = uhci->skel_ls_control_qh; |
607 | else { | 677 | else { |
608 | qh->skel = uhci->skel_fs_control_qh; | 678 | qh->skel = uhci->skel_fs_control_qh; |
609 | uhci_inc_fsbr(uhci, urb); | 679 | uhci_add_fsbr(uhci, urb); |
610 | } | 680 | } |
681 | |||
682 | urb->actual_length = -8; /* Account for the SETUP packet */ | ||
611 | return 0; | 683 | return 0; |
612 | 684 | ||
613 | nomem: | 685 | nomem: |
614 | /* Remove the dummy TD from the td_list so it doesn't get freed */ | 686 | /* Remove the dummy TD from the td_list so it doesn't get freed */ |
615 | uhci_remove_td_from_urb(qh->dummy_td); | 687 | uhci_remove_td_from_urbp(qh->dummy_td); |
616 | return -ENOMEM; | 688 | return -ENOMEM; |
617 | } | 689 | } |
618 | 690 | ||
619 | /* | 691 | /* |
620 | * If control-IN transfer was short, the status packet wasn't sent. | ||
621 | * This routine changes the element pointer in the QH to point at the | ||
622 | * status TD. It's safe to do this even while the QH is live, because | ||
623 | * the hardware only updates the element pointer following a successful | ||
624 | * transfer. The inactive TD for the short packet won't cause an update, | ||
625 | * so the pointer won't get overwritten. The next time the controller | ||
626 | * sees this QH, it will send the status packet. | ||
627 | */ | ||
628 | static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb) | ||
629 | { | ||
630 | struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; | ||
631 | struct uhci_td *td; | ||
632 | |||
633 | urbp->short_transfer = 1; | ||
634 | |||
635 | td = list_entry(urbp->td_list.prev, struct uhci_td, list); | ||
636 | urbp->qh->element = cpu_to_le32(td->dma_handle); | ||
637 | |||
638 | return -EINPROGRESS; | ||
639 | } | ||
640 | |||
641 | |||
642 | static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) | ||
643 | { | ||
644 | struct list_head *tmp, *head; | ||
645 | struct urb_priv *urbp = urb->hcpriv; | ||
646 | struct uhci_td *td; | ||
647 | unsigned int status; | ||
648 | int ret = 0; | ||
649 | |||
650 | head = &urbp->td_list; | ||
651 | if (urbp->short_transfer) { | ||
652 | tmp = head->prev; | ||
653 | goto status_stage; | ||
654 | } | ||
655 | |||
656 | urb->actual_length = 0; | ||
657 | |||
658 | tmp = head->next; | ||
659 | td = list_entry(tmp, struct uhci_td, list); | ||
660 | |||
661 | /* The first TD is the SETUP stage, check the status, but skip */ | ||
662 | /* the count */ | ||
663 | status = uhci_status_bits(td_status(td)); | ||
664 | if (status & TD_CTRL_ACTIVE) | ||
665 | return -EINPROGRESS; | ||
666 | |||
667 | if (status) | ||
668 | goto td_error; | ||
669 | |||
670 | /* The rest of the TDs (but the last) are data */ | ||
671 | tmp = tmp->next; | ||
672 | while (tmp != head && tmp->next != head) { | ||
673 | unsigned int ctrlstat; | ||
674 | |||
675 | td = list_entry(tmp, struct uhci_td, list); | ||
676 | tmp = tmp->next; | ||
677 | |||
678 | ctrlstat = td_status(td); | ||
679 | status = uhci_status_bits(ctrlstat); | ||
680 | if (status & TD_CTRL_ACTIVE) | ||
681 | return -EINPROGRESS; | ||
682 | |||
683 | urb->actual_length += uhci_actual_length(ctrlstat); | ||
684 | |||
685 | if (status) | ||
686 | goto td_error; | ||
687 | |||
688 | /* Check to see if we received a short packet */ | ||
689 | if (uhci_actual_length(ctrlstat) < | ||
690 | uhci_expected_length(td_token(td))) { | ||
691 | if (urb->transfer_flags & URB_SHORT_NOT_OK) { | ||
692 | ret = -EREMOTEIO; | ||
693 | goto err; | ||
694 | } | ||
695 | |||
696 | return usb_control_retrigger_status(uhci, urb); | ||
697 | } | ||
698 | } | ||
699 | |||
700 | status_stage: | ||
701 | td = list_entry(tmp, struct uhci_td, list); | ||
702 | |||
703 | /* Control status stage */ | ||
704 | status = td_status(td); | ||
705 | |||
706 | #ifdef I_HAVE_BUGGY_APC_BACKUPS | ||
707 | /* APC BackUPS Pro kludge */ | ||
708 | /* It tries to send all of the descriptor instead of the amount */ | ||
709 | /* we requested */ | ||
710 | if (status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */ | ||
711 | status & TD_CTRL_ACTIVE && | ||
712 | status & TD_CTRL_NAK) | ||
713 | return 0; | ||
714 | #endif | ||
715 | |||
716 | status = uhci_status_bits(status); | ||
717 | if (status & TD_CTRL_ACTIVE) | ||
718 | return -EINPROGRESS; | ||
719 | |||
720 | if (status) | ||
721 | goto td_error; | ||
722 | |||
723 | return 0; | ||
724 | |||
725 | td_error: | ||
726 | ret = uhci_map_status(status, uhci_packetout(td_token(td))); | ||
727 | |||
728 | err: | ||
729 | if ((debug == 1 && ret != -EPIPE) || debug > 1) { | ||
730 | /* Some debugging code */ | ||
731 | dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", | ||
732 | __FUNCTION__, status); | ||
733 | |||
734 | if (errbuf) { | ||
735 | /* Print the chain for debugging purposes */ | ||
736 | uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); | ||
737 | lprintk(errbuf); | ||
738 | } | ||
739 | } | ||
740 | |||
741 | /* Note that the queue has stopped */ | ||
742 | urbp->qh->element = UHCI_PTR_TERM; | ||
743 | urbp->qh->is_stopped = 1; | ||
744 | return ret; | ||
745 | } | ||
746 | |||
747 | /* | ||
748 | * Common submit for bulk and interrupt | 692 | * Common submit for bulk and interrupt |
749 | */ | 693 | */ |
750 | static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | 694 | static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, |
@@ -756,6 +700,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
756 | int len = urb->transfer_buffer_length; | 700 | int len = urb->transfer_buffer_length; |
757 | dma_addr_t data = urb->transfer_dma; | 701 | dma_addr_t data = urb->transfer_dma; |
758 | __le32 *plink; | 702 | __le32 *plink; |
703 | struct urb_priv *urbp = urb->hcpriv; | ||
759 | unsigned int toggle; | 704 | unsigned int toggle; |
760 | 705 | ||
761 | if (len < 0) | 706 | if (len < 0) |
@@ -793,7 +738,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
793 | goto nomem; | 738 | goto nomem; |
794 | *plink = cpu_to_le32(td->dma_handle); | 739 | *plink = cpu_to_le32(td->dma_handle); |
795 | } | 740 | } |
796 | uhci_add_td_to_urb(urb, td); | 741 | uhci_add_td_to_urbp(td, urbp); |
797 | uhci_fill_td(td, status, | 742 | uhci_fill_td(td, status, |
798 | destination | uhci_explen(pktsze) | | 743 | destination | uhci_explen(pktsze) | |
799 | (toggle << TD_TOKEN_TOGGLE_SHIFT), | 744 | (toggle << TD_TOKEN_TOGGLE_SHIFT), |
@@ -821,7 +766,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
821 | goto nomem; | 766 | goto nomem; |
822 | *plink = cpu_to_le32(td->dma_handle); | 767 | *plink = cpu_to_le32(td->dma_handle); |
823 | 768 | ||
824 | uhci_add_td_to_urb(urb, td); | 769 | uhci_add_td_to_urbp(td, urbp); |
825 | uhci_fill_td(td, status, | 770 | uhci_fill_td(td, status, |
826 | destination | uhci_explen(0) | | 771 | destination | uhci_explen(0) | |
827 | (toggle << TD_TOKEN_TOGGLE_SHIFT), | 772 | (toggle << TD_TOKEN_TOGGLE_SHIFT), |
@@ -851,6 +796,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
851 | wmb(); | 796 | wmb(); |
852 | qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); | 797 | qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); |
853 | qh->dummy_td = td; | 798 | qh->dummy_td = td; |
799 | qh->period = urb->interval; | ||
854 | 800 | ||
855 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | 801 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), |
856 | usb_pipeout(urb->pipe), toggle); | 802 | usb_pipeout(urb->pipe), toggle); |
@@ -858,90 +804,10 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
858 | 804 | ||
859 | nomem: | 805 | nomem: |
860 | /* Remove the dummy TD from the td_list so it doesn't get freed */ | 806 | /* Remove the dummy TD from the td_list so it doesn't get freed */ |
861 | uhci_remove_td_from_urb(qh->dummy_td); | 807 | uhci_remove_td_from_urbp(qh->dummy_td); |
862 | return -ENOMEM; | 808 | return -ENOMEM; |
863 | } | 809 | } |
864 | 810 | ||
865 | /* | ||
866 | * Common result for bulk and interrupt | ||
867 | */ | ||
868 | static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) | ||
869 | { | ||
870 | struct urb_priv *urbp = urb->hcpriv; | ||
871 | struct uhci_td *td; | ||
872 | unsigned int status = 0; | ||
873 | int ret = 0; | ||
874 | |||
875 | urb->actual_length = 0; | ||
876 | |||
877 | list_for_each_entry(td, &urbp->td_list, list) { | ||
878 | unsigned int ctrlstat = td_status(td); | ||
879 | |||
880 | status = uhci_status_bits(ctrlstat); | ||
881 | if (status & TD_CTRL_ACTIVE) | ||
882 | return -EINPROGRESS; | ||
883 | |||
884 | urb->actual_length += uhci_actual_length(ctrlstat); | ||
885 | |||
886 | if (status) | ||
887 | goto td_error; | ||
888 | |||
889 | if (uhci_actual_length(ctrlstat) < | ||
890 | uhci_expected_length(td_token(td))) { | ||
891 | if (urb->transfer_flags & URB_SHORT_NOT_OK) { | ||
892 | ret = -EREMOTEIO; | ||
893 | goto err; | ||
894 | } | ||
895 | |||
896 | /* | ||
897 | * This URB stopped short of its end. We have to | ||
898 | * fix up the toggles of the following URBs on the | ||
899 | * queue and restart the queue. | ||
900 | * | ||
901 | * Do this only the first time we encounter the | ||
902 | * short URB. | ||
903 | */ | ||
904 | if (!urbp->short_transfer) { | ||
905 | urbp->short_transfer = 1; | ||
906 | urbp->qh->initial_toggle = | ||
907 | uhci_toggle(td_token(td)) ^ 1; | ||
908 | uhci_fixup_toggles(urbp->qh, 1); | ||
909 | |||
910 | td = list_entry(urbp->td_list.prev, | ||
911 | struct uhci_td, list); | ||
912 | urbp->qh->element = td->link; | ||
913 | } | ||
914 | break; | ||
915 | } | ||
916 | } | ||
917 | |||
918 | return 0; | ||
919 | |||
920 | td_error: | ||
921 | ret = uhci_map_status(status, uhci_packetout(td_token(td))); | ||
922 | |||
923 | if ((debug == 1 && ret != -EPIPE) || debug > 1) { | ||
924 | /* Some debugging code */ | ||
925 | dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", | ||
926 | __FUNCTION__, status); | ||
927 | |||
928 | if (debug > 1 && errbuf) { | ||
929 | /* Print the chain for debugging purposes */ | ||
930 | uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); | ||
931 | lprintk(errbuf); | ||
932 | } | ||
933 | } | ||
934 | err: | ||
935 | |||
936 | /* Note that the queue has stopped and save the next toggle value */ | ||
937 | urbp->qh->element = UHCI_PTR_TERM; | ||
938 | urbp->qh->is_stopped = 1; | ||
939 | urbp->qh->needs_fixup = 1; | ||
940 | urbp->qh->initial_toggle = uhci_toggle(td_token(td)) ^ | ||
941 | (ret == -EREMOTEIO); | ||
942 | return ret; | ||
943 | } | ||
944 | |||
945 | static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, | 811 | static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, |
946 | struct uhci_qh *qh) | 812 | struct uhci_qh *qh) |
947 | { | 813 | { |
@@ -954,22 +820,163 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, | |||
954 | qh->skel = uhci->skel_bulk_qh; | 820 | qh->skel = uhci->skel_bulk_qh; |
955 | ret = uhci_submit_common(uhci, urb, qh); | 821 | ret = uhci_submit_common(uhci, urb, qh); |
956 | if (ret == 0) | 822 | if (ret == 0) |
957 | uhci_inc_fsbr(uhci, urb); | 823 | uhci_add_fsbr(uhci, urb); |
958 | return ret; | 824 | return ret; |
959 | } | 825 | } |
960 | 826 | ||
961 | static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, | 827 | static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, |
962 | struct uhci_qh *qh) | 828 | struct uhci_qh *qh) |
963 | { | 829 | { |
830 | int exponent; | ||
831 | |||
964 | /* USB 1.1 interrupt transfers only involve one packet per interval. | 832 | /* USB 1.1 interrupt transfers only involve one packet per interval. |
965 | * Drivers can submit URBs of any length, but longer ones will need | 833 | * Drivers can submit URBs of any length, but longer ones will need |
966 | * multiple intervals to complete. | 834 | * multiple intervals to complete. |
967 | */ | 835 | */ |
968 | qh->skel = uhci->skelqh[__interval_to_skel(urb->interval)]; | 836 | |
837 | /* Figure out which power-of-two queue to use */ | ||
838 | for (exponent = 7; exponent >= 0; --exponent) { | ||
839 | if ((1 << exponent) <= urb->interval) | ||
840 | break; | ||
841 | } | ||
842 | if (exponent < 0) | ||
843 | return -EINVAL; | ||
844 | urb->interval = 1 << exponent; | ||
845 | |||
846 | if (qh->period == 0) | ||
847 | qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)]; | ||
848 | else if (qh->period != urb->interval) | ||
849 | return -EINVAL; /* Can't change the period */ | ||
850 | |||
969 | return uhci_submit_common(uhci, urb, qh); | 851 | return uhci_submit_common(uhci, urb, qh); |
970 | } | 852 | } |
971 | 853 | ||
972 | /* | 854 | /* |
855 | * Fix up the data structures following a short transfer | ||
856 | */ | ||
857 | static int uhci_fixup_short_transfer(struct uhci_hcd *uhci, | ||
858 | struct uhci_qh *qh, struct urb_priv *urbp) | ||
859 | { | ||
860 | struct uhci_td *td; | ||
861 | struct list_head *tmp; | ||
862 | int ret; | ||
863 | |||
864 | td = list_entry(urbp->td_list.prev, struct uhci_td, list); | ||
865 | if (qh->type == USB_ENDPOINT_XFER_CONTROL) { | ||
866 | |||
867 | /* When a control transfer is short, we have to restart | ||
868 | * the queue at the status stage transaction, which is | ||
869 | * the last TD. */ | ||
870 | WARN_ON(list_empty(&urbp->td_list)); | ||
871 | qh->element = cpu_to_le32(td->dma_handle); | ||
872 | tmp = td->list.prev; | ||
873 | ret = -EINPROGRESS; | ||
874 | |||
875 | } else { | ||
876 | |||
877 | /* When a bulk/interrupt transfer is short, we have to | ||
878 | * fix up the toggles of the following URBs on the queue | ||
879 | * before restarting the queue at the next URB. */ | ||
880 | qh->initial_toggle = uhci_toggle(td_token(qh->post_td)) ^ 1; | ||
881 | uhci_fixup_toggles(qh, 1); | ||
882 | |||
883 | if (list_empty(&urbp->td_list)) | ||
884 | td = qh->post_td; | ||
885 | qh->element = td->link; | ||
886 | tmp = urbp->td_list.prev; | ||
887 | ret = 0; | ||
888 | } | ||
889 | |||
890 | /* Remove all the TDs we skipped over, from tmp back to the start */ | ||
891 | while (tmp != &urbp->td_list) { | ||
892 | td = list_entry(tmp, struct uhci_td, list); | ||
893 | tmp = tmp->prev; | ||
894 | |||
895 | uhci_remove_td_from_urbp(td); | ||
896 | uhci_free_td(uhci, td); | ||
897 | } | ||
898 | return ret; | ||
899 | } | ||
900 | |||
901 | /* | ||
902 | * Common result for control, bulk, and interrupt | ||
903 | */ | ||
904 | static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) | ||
905 | { | ||
906 | struct urb_priv *urbp = urb->hcpriv; | ||
907 | struct uhci_qh *qh = urbp->qh; | ||
908 | struct uhci_td *td, *tmp; | ||
909 | unsigned status; | ||
910 | int ret = 0; | ||
911 | |||
912 | list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { | ||
913 | unsigned int ctrlstat; | ||
914 | int len; | ||
915 | |||
916 | ctrlstat = td_status(td); | ||
917 | status = uhci_status_bits(ctrlstat); | ||
918 | if (status & TD_CTRL_ACTIVE) | ||
919 | return -EINPROGRESS; | ||
920 | |||
921 | len = uhci_actual_length(ctrlstat); | ||
922 | urb->actual_length += len; | ||
923 | |||
924 | if (status) { | ||
925 | ret = uhci_map_status(status, | ||
926 | uhci_packetout(td_token(td))); | ||
927 | if ((debug == 1 && ret != -EPIPE) || debug > 1) { | ||
928 | /* Some debugging code */ | ||
929 | dev_dbg(&urb->dev->dev, | ||
930 | "%s: failed with status %x\n", | ||
931 | __FUNCTION__, status); | ||
932 | |||
933 | if (debug > 1 && errbuf) { | ||
934 | /* Print the chain for debugging */ | ||
935 | uhci_show_qh(urbp->qh, errbuf, | ||
936 | ERRBUF_LEN, 0); | ||
937 | lprintk(errbuf); | ||
938 | } | ||
939 | } | ||
940 | |||
941 | } else if (len < uhci_expected_length(td_token(td))) { | ||
942 | |||
943 | /* We received a short packet */ | ||
944 | if (urb->transfer_flags & URB_SHORT_NOT_OK) | ||
945 | ret = -EREMOTEIO; | ||
946 | else if (ctrlstat & TD_CTRL_SPD) | ||
947 | ret = 1; | ||
948 | } | ||
949 | |||
950 | uhci_remove_td_from_urbp(td); | ||
951 | if (qh->post_td) | ||
952 | uhci_free_td(uhci, qh->post_td); | ||
953 | qh->post_td = td; | ||
954 | |||
955 | if (ret != 0) | ||
956 | goto err; | ||
957 | } | ||
958 | return ret; | ||
959 | |||
960 | err: | ||
961 | if (ret < 0) { | ||
962 | /* In case a control transfer gets an error | ||
963 | * during the setup stage */ | ||
964 | urb->actual_length = max(urb->actual_length, 0); | ||
965 | |||
966 | /* Note that the queue has stopped and save | ||
967 | * the next toggle value */ | ||
968 | qh->element = UHCI_PTR_TERM; | ||
969 | qh->is_stopped = 1; | ||
970 | qh->needs_fixup = (qh->type != USB_ENDPOINT_XFER_CONTROL); | ||
971 | qh->initial_toggle = uhci_toggle(td_token(td)) ^ | ||
972 | (ret == -EREMOTEIO); | ||
973 | |||
974 | } else /* Short packet received */ | ||
975 | ret = uhci_fixup_short_transfer(uhci, qh, urbp); | ||
976 | return ret; | ||
977 | } | ||
978 | |||
979 | /* | ||
973 | * Isochronous transfers | 980 | * Isochronous transfers |
974 | */ | 981 | */ |
975 | static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | 982 | static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, |
@@ -980,38 +987,57 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | |||
980 | unsigned long destination, status; | 987 | unsigned long destination, status; |
981 | struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; | 988 | struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; |
982 | 989 | ||
983 | if (urb->number_of_packets > 900) /* 900? Why? */ | 990 | /* Values must not be too big (could overflow below) */ |
991 | if (urb->interval >= UHCI_NUMFRAMES || | ||
992 | urb->number_of_packets >= UHCI_NUMFRAMES) | ||
984 | return -EFBIG; | 993 | return -EFBIG; |
985 | 994 | ||
986 | status = TD_CTRL_ACTIVE | TD_CTRL_IOS; | 995 | /* Check the period and figure out the starting frame number */ |
987 | destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); | 996 | if (qh->period == 0) { |
988 | 997 | if (urb->transfer_flags & URB_ISO_ASAP) { | |
989 | /* Figure out the starting frame number */ | ||
990 | if (urb->transfer_flags & URB_ISO_ASAP) { | ||
991 | if (list_empty(&qh->queue)) { | ||
992 | uhci_get_current_frame_number(uhci); | 998 | uhci_get_current_frame_number(uhci); |
993 | urb->start_frame = (uhci->frame_number + 10); | 999 | urb->start_frame = uhci->frame_number + 10; |
1000 | } else { | ||
1001 | i = urb->start_frame - uhci->last_iso_frame; | ||
1002 | if (i <= 0 || i >= UHCI_NUMFRAMES) | ||
1003 | return -EINVAL; | ||
1004 | } | ||
1005 | } else if (qh->period != urb->interval) { | ||
1006 | return -EINVAL; /* Can't change the period */ | ||
994 | 1007 | ||
995 | } else { /* Go right after the last one */ | 1008 | } else { /* Pick up where the last URB leaves off */ |
996 | struct urb *last_urb; | 1009 | if (list_empty(&qh->queue)) { |
1010 | frame = qh->iso_frame; | ||
1011 | } else { | ||
1012 | struct urb *lurb; | ||
997 | 1013 | ||
998 | last_urb = list_entry(qh->queue.prev, | 1014 | lurb = list_entry(qh->queue.prev, |
999 | struct urb_priv, node)->urb; | 1015 | struct urb_priv, node)->urb; |
1000 | urb->start_frame = (last_urb->start_frame + | 1016 | frame = lurb->start_frame + |
1001 | last_urb->number_of_packets * | 1017 | lurb->number_of_packets * |
1002 | last_urb->interval); | 1018 | lurb->interval; |
1003 | } | 1019 | } |
1004 | } else { | 1020 | if (urb->transfer_flags & URB_ISO_ASAP) |
1005 | /* FIXME: Sanity check */ | 1021 | urb->start_frame = frame; |
1022 | else if (urb->start_frame != frame) | ||
1023 | return -EINVAL; | ||
1006 | } | 1024 | } |
1007 | urb->start_frame &= (UHCI_NUMFRAMES - 1); | 1025 | |
1026 | /* Make sure we won't have to go too far into the future */ | ||
1027 | if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES, | ||
1028 | urb->start_frame + urb->number_of_packets * | ||
1029 | urb->interval)) | ||
1030 | return -EFBIG; | ||
1031 | |||
1032 | status = TD_CTRL_ACTIVE | TD_CTRL_IOS; | ||
1033 | destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); | ||
1008 | 1034 | ||
1009 | for (i = 0; i < urb->number_of_packets; i++) { | 1035 | for (i = 0; i < urb->number_of_packets; i++) { |
1010 | td = uhci_alloc_td(uhci); | 1036 | td = uhci_alloc_td(uhci); |
1011 | if (!td) | 1037 | if (!td) |
1012 | return -ENOMEM; | 1038 | return -ENOMEM; |
1013 | 1039 | ||
1014 | uhci_add_td_to_urb(urb, td); | 1040 | uhci_add_td_to_urbp(td, urbp); |
1015 | uhci_fill_td(td, status, destination | | 1041 | uhci_fill_td(td, status, destination | |
1016 | uhci_explen(urb->iso_frame_desc[i].length), | 1042 | uhci_explen(urb->iso_frame_desc[i].length), |
1017 | urb->transfer_dma + | 1043 | urb->transfer_dma + |
@@ -1022,12 +1048,19 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | |||
1022 | td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); | 1048 | td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); |
1023 | 1049 | ||
1024 | qh->skel = uhci->skel_iso_qh; | 1050 | qh->skel = uhci->skel_iso_qh; |
1051 | qh->period = urb->interval; | ||
1025 | 1052 | ||
1026 | /* Add the TDs to the frame list */ | 1053 | /* Add the TDs to the frame list */ |
1027 | frame = urb->start_frame; | 1054 | frame = urb->start_frame; |
1028 | list_for_each_entry(td, &urbp->td_list, list) { | 1055 | list_for_each_entry(td, &urbp->td_list, list) { |
1029 | uhci_insert_td_in_frame_list(uhci, td, frame); | 1056 | uhci_insert_td_in_frame_list(uhci, td, frame); |
1030 | frame += urb->interval; | 1057 | frame += qh->period; |
1058 | } | ||
1059 | |||
1060 | if (list_empty(&qh->queue)) { | ||
1061 | qh->iso_packet_desc = &urb->iso_frame_desc[0]; | ||
1062 | qh->iso_frame = urb->start_frame; | ||
1063 | qh->iso_status = 0; | ||
1031 | } | 1064 | } |
1032 | 1065 | ||
1033 | return 0; | 1066 | return 0; |
@@ -1035,37 +1068,44 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | |||
1035 | 1068 | ||
1036 | static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) | 1069 | static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) |
1037 | { | 1070 | { |
1038 | struct uhci_td *td; | 1071 | struct uhci_td *td, *tmp; |
1039 | struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; | 1072 | struct urb_priv *urbp = urb->hcpriv; |
1040 | int status; | 1073 | struct uhci_qh *qh = urbp->qh; |
1041 | int i, ret = 0; | ||
1042 | |||
1043 | urb->actual_length = urb->error_count = 0; | ||
1044 | 1074 | ||
1045 | i = 0; | 1075 | list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { |
1046 | list_for_each_entry(td, &urbp->td_list, list) { | 1076 | unsigned int ctrlstat; |
1077 | int status; | ||
1047 | int actlength; | 1078 | int actlength; |
1048 | unsigned int ctrlstat = td_status(td); | ||
1049 | 1079 | ||
1050 | if (ctrlstat & TD_CTRL_ACTIVE) | 1080 | if (uhci_frame_before_eq(uhci->cur_iso_frame, qh->iso_frame)) |
1051 | return -EINPROGRESS; | 1081 | return -EINPROGRESS; |
1052 | 1082 | ||
1053 | actlength = uhci_actual_length(ctrlstat); | 1083 | uhci_remove_tds_from_frame(uhci, qh->iso_frame); |
1054 | urb->iso_frame_desc[i].actual_length = actlength; | 1084 | |
1055 | urb->actual_length += actlength; | 1085 | ctrlstat = td_status(td); |
1086 | if (ctrlstat & TD_CTRL_ACTIVE) { | ||
1087 | status = -EXDEV; /* TD was added too late? */ | ||
1088 | } else { | ||
1089 | status = uhci_map_status(uhci_status_bits(ctrlstat), | ||
1090 | usb_pipeout(urb->pipe)); | ||
1091 | actlength = uhci_actual_length(ctrlstat); | ||
1092 | |||
1093 | urb->actual_length += actlength; | ||
1094 | qh->iso_packet_desc->actual_length = actlength; | ||
1095 | qh->iso_packet_desc->status = status; | ||
1096 | } | ||
1056 | 1097 | ||
1057 | status = uhci_map_status(uhci_status_bits(ctrlstat), | ||
1058 | usb_pipeout(urb->pipe)); | ||
1059 | urb->iso_frame_desc[i].status = status; | ||
1060 | if (status) { | 1098 | if (status) { |
1061 | urb->error_count++; | 1099 | urb->error_count++; |
1062 | ret = status; | 1100 | qh->iso_status = status; |
1063 | } | 1101 | } |
1064 | 1102 | ||
1065 | i++; | 1103 | uhci_remove_td_from_urbp(td); |
1104 | uhci_free_td(uhci, td); | ||
1105 | qh->iso_frame += qh->period; | ||
1106 | ++qh->iso_packet_desc; | ||
1066 | } | 1107 | } |
1067 | 1108 | return qh->iso_status; | |
1068 | return ret; | ||
1069 | } | 1109 | } |
1070 | 1110 | ||
1071 | static int uhci_urb_enqueue(struct usb_hcd *hcd, | 1111 | static int uhci_urb_enqueue(struct usb_hcd *hcd, |
@@ -1099,14 +1139,14 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, | |||
1099 | } | 1139 | } |
1100 | urbp->qh = qh; | 1140 | urbp->qh = qh; |
1101 | 1141 | ||
1102 | switch (usb_pipetype(urb->pipe)) { | 1142 | switch (qh->type) { |
1103 | case PIPE_CONTROL: | 1143 | case USB_ENDPOINT_XFER_CONTROL: |
1104 | ret = uhci_submit_control(uhci, urb, qh); | 1144 | ret = uhci_submit_control(uhci, urb, qh); |
1105 | break; | 1145 | break; |
1106 | case PIPE_BULK: | 1146 | case USB_ENDPOINT_XFER_BULK: |
1107 | ret = uhci_submit_bulk(uhci, urb, qh); | 1147 | ret = uhci_submit_bulk(uhci, urb, qh); |
1108 | break; | 1148 | break; |
1109 | case PIPE_INTERRUPT: | 1149 | case USB_ENDPOINT_XFER_INT: |
1110 | if (list_empty(&qh->queue)) { | 1150 | if (list_empty(&qh->queue)) { |
1111 | bustime = usb_check_bandwidth(urb->dev, urb); | 1151 | bustime = usb_check_bandwidth(urb->dev, urb); |
1112 | if (bustime < 0) | 1152 | if (bustime < 0) |
@@ -1125,7 +1165,8 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, | |||
1125 | ret = uhci_submit_interrupt(uhci, urb, qh); | 1165 | ret = uhci_submit_interrupt(uhci, urb, qh); |
1126 | } | 1166 | } |
1127 | break; | 1167 | break; |
1128 | case PIPE_ISOCHRONOUS: | 1168 | case USB_ENDPOINT_XFER_ISOC: |
1169 | urb->error_count = 0; | ||
1129 | bustime = usb_check_bandwidth(urb->dev, urb); | 1170 | bustime = usb_check_bandwidth(urb->dev, urb); |
1130 | if (bustime < 0) { | 1171 | if (bustime < 0) { |
1131 | ret = bustime; | 1172 | ret = bustime; |
@@ -1146,9 +1187,12 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, | |||
1146 | 1187 | ||
1147 | /* If the new URB is the first and only one on this QH then either | 1188 | /* If the new URB is the first and only one on this QH then either |
1148 | * the QH is new and idle or else it's unlinked and waiting to | 1189 | * the QH is new and idle or else it's unlinked and waiting to |
1149 | * become idle, so we can activate it right away. */ | 1190 | * become idle, so we can activate it right away. But only if the |
1150 | if (qh->queue.next == &urbp->node) | 1191 | * queue isn't stopped. */ |
1192 | if (qh->queue.next == &urbp->node && !qh->is_stopped) { | ||
1151 | uhci_activate_qh(uhci, qh); | 1193 | uhci_activate_qh(uhci, qh); |
1194 | uhci_urbp_wants_fsbr(uhci, urbp); | ||
1195 | } | ||
1152 | goto done; | 1196 | goto done; |
1153 | 1197 | ||
1154 | err_submit_failed: | 1198 | err_submit_failed: |
@@ -1168,16 +1212,26 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | |||
1168 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 1212 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
1169 | unsigned long flags; | 1213 | unsigned long flags; |
1170 | struct urb_priv *urbp; | 1214 | struct urb_priv *urbp; |
1215 | struct uhci_qh *qh; | ||
1171 | 1216 | ||
1172 | spin_lock_irqsave(&uhci->lock, flags); | 1217 | spin_lock_irqsave(&uhci->lock, flags); |
1173 | urbp = urb->hcpriv; | 1218 | urbp = urb->hcpriv; |
1174 | if (!urbp) /* URB was never linked! */ | 1219 | if (!urbp) /* URB was never linked! */ |
1175 | goto done; | 1220 | goto done; |
1221 | qh = urbp->qh; | ||
1176 | 1222 | ||
1177 | /* Remove Isochronous TDs from the frame list ASAP */ | 1223 | /* Remove Isochronous TDs from the frame list ASAP */ |
1178 | if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) | 1224 | if (qh->type == USB_ENDPOINT_XFER_ISOC) { |
1179 | uhci_unlink_isochronous_tds(uhci, urb); | 1225 | uhci_unlink_isochronous_tds(uhci, urb); |
1180 | uhci_unlink_qh(uhci, urbp->qh); | 1226 | mb(); |
1227 | |||
1228 | /* If the URB has already started, update the QH unlink time */ | ||
1229 | uhci_get_current_frame_number(uhci); | ||
1230 | if (uhci_frame_before_eq(urb->start_frame, uhci->frame_number)) | ||
1231 | qh->unlink_frame = uhci->frame_number; | ||
1232 | } | ||
1233 | |||
1234 | uhci_unlink_qh(uhci, qh); | ||
1181 | 1235 | ||
1182 | done: | 1236 | done: |
1183 | spin_unlock_irqrestore(&uhci->lock, flags); | 1237 | spin_unlock_irqrestore(&uhci->lock, flags); |
@@ -1194,22 +1248,17 @@ __acquires(uhci->lock) | |||
1194 | { | 1248 | { |
1195 | struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; | 1249 | struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; |
1196 | 1250 | ||
1197 | /* Isochronous TDs get unlinked directly from the frame list */ | 1251 | /* When giving back the first URB in an Isochronous queue, |
1198 | if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) | 1252 | * reinitialize the QH's iso-related members for the next URB. */ |
1199 | uhci_unlink_isochronous_tds(uhci, urb); | 1253 | if (qh->type == USB_ENDPOINT_XFER_ISOC && |
1200 | 1254 | urbp->node.prev == &qh->queue && | |
1201 | /* If the URB isn't first on its queue, adjust the link pointer | 1255 | urbp->node.next != &qh->queue) { |
1202 | * of the last TD in the previous URB. */ | 1256 | struct urb *nurb = list_entry(urbp->node.next, |
1203 | else if (qh->queue.next != &urbp->node) { | 1257 | struct urb_priv, node)->urb; |
1204 | struct urb_priv *purbp; | 1258 | |
1205 | struct uhci_td *ptd, *ltd; | 1259 | qh->iso_packet_desc = &nurb->iso_frame_desc[0]; |
1206 | 1260 | qh->iso_frame = nurb->start_frame; | |
1207 | purbp = list_entry(urbp->node.prev, struct urb_priv, node); | 1261 | qh->iso_status = 0; |
1208 | ptd = list_entry(purbp->td_list.prev, struct uhci_td, | ||
1209 | list); | ||
1210 | ltd = list_entry(urbp->td_list.prev, struct uhci_td, | ||
1211 | list); | ||
1212 | ptd->link = ltd->link; | ||
1213 | } | 1262 | } |
1214 | 1263 | ||
1215 | /* Take the URB off the QH's queue. If the queue is now empty, | 1264 | /* Take the URB off the QH's queue. If the queue is now empty, |
@@ -1221,16 +1270,15 @@ __acquires(uhci->lock) | |||
1221 | qh->needs_fixup = 0; | 1270 | qh->needs_fixup = 0; |
1222 | } | 1271 | } |
1223 | 1272 | ||
1224 | uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ | ||
1225 | uhci_free_urb_priv(uhci, urbp); | 1273 | uhci_free_urb_priv(uhci, urbp); |
1226 | 1274 | ||
1227 | switch (usb_pipetype(urb->pipe)) { | 1275 | switch (qh->type) { |
1228 | case PIPE_ISOCHRONOUS: | 1276 | case USB_ENDPOINT_XFER_ISOC: |
1229 | /* Release bandwidth for Interrupt or Isoc. transfers */ | 1277 | /* Release bandwidth for Interrupt or Isoc. transfers */ |
1230 | if (urb->bandwidth) | 1278 | if (urb->bandwidth) |
1231 | usb_release_bandwidth(urb->dev, urb, 1); | 1279 | usb_release_bandwidth(urb->dev, urb, 1); |
1232 | break; | 1280 | break; |
1233 | case PIPE_INTERRUPT: | 1281 | case USB_ENDPOINT_XFER_INT: |
1234 | /* Release bandwidth for Interrupt or Isoc. transfers */ | 1282 | /* Release bandwidth for Interrupt or Isoc. transfers */ |
1235 | /* Make sure we don't release if we have a queued URB */ | 1283 | /* Make sure we don't release if we have a queued URB */ |
1236 | if (list_empty(&qh->queue) && urb->bandwidth) | 1284 | if (list_empty(&qh->queue) && urb->bandwidth) |
@@ -1252,6 +1300,7 @@ __acquires(uhci->lock) | |||
1252 | uhci_unlink_qh(uhci, qh); | 1300 | uhci_unlink_qh(uhci, qh); |
1253 | 1301 | ||
1254 | /* Bandwidth stuff not yet implemented */ | 1302 | /* Bandwidth stuff not yet implemented */ |
1303 | qh->period = 0; | ||
1255 | } | 1304 | } |
1256 | } | 1305 | } |
1257 | 1306 | ||
@@ -1273,17 +1322,10 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, | |||
1273 | urbp = list_entry(qh->queue.next, struct urb_priv, node); | 1322 | urbp = list_entry(qh->queue.next, struct urb_priv, node); |
1274 | urb = urbp->urb; | 1323 | urb = urbp->urb; |
1275 | 1324 | ||
1276 | switch (usb_pipetype(urb->pipe)) { | 1325 | if (qh->type == USB_ENDPOINT_XFER_ISOC) |
1277 | case PIPE_CONTROL: | ||
1278 | status = uhci_result_control(uhci, urb); | ||
1279 | break; | ||
1280 | case PIPE_ISOCHRONOUS: | ||
1281 | status = uhci_result_isochronous(uhci, urb); | 1326 | status = uhci_result_isochronous(uhci, urb); |
1282 | break; | 1327 | else |
1283 | default: /* PIPE_BULK or PIPE_INTERRUPT */ | ||
1284 | status = uhci_result_common(uhci, urb); | 1328 | status = uhci_result_common(uhci, urb); |
1285 | break; | ||
1286 | } | ||
1287 | if (status == -EINPROGRESS) | 1329 | if (status == -EINPROGRESS) |
1288 | break; | 1330 | break; |
1289 | 1331 | ||
@@ -1291,31 +1333,43 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, | |||
1291 | if (urb->status == -EINPROGRESS) /* Not dequeued */ | 1333 | if (urb->status == -EINPROGRESS) /* Not dequeued */ |
1292 | urb->status = status; | 1334 | urb->status = status; |
1293 | else | 1335 | else |
1294 | status = -ECONNRESET; | 1336 | status = ECONNRESET; /* Not -ECONNRESET */ |
1295 | spin_unlock(&urb->lock); | 1337 | spin_unlock(&urb->lock); |
1296 | 1338 | ||
1297 | /* Dequeued but completed URBs can't be given back unless | 1339 | /* Dequeued but completed URBs can't be given back unless |
1298 | * the QH is stopped or has finished unlinking. */ | 1340 | * the QH is stopped or has finished unlinking. */ |
1299 | if (status == -ECONNRESET && | 1341 | if (status == ECONNRESET) { |
1300 | !(qh->is_stopped || QH_FINISHED_UNLINKING(qh))) | 1342 | if (QH_FINISHED_UNLINKING(qh)) |
1301 | return; | 1343 | qh->is_stopped = 1; |
1344 | else if (!qh->is_stopped) | ||
1345 | return; | ||
1346 | } | ||
1302 | 1347 | ||
1303 | uhci_giveback_urb(uhci, qh, urb, regs); | 1348 | uhci_giveback_urb(uhci, qh, urb, regs); |
1304 | if (qh->is_stopped) | 1349 | if (status < 0) |
1305 | break; | 1350 | break; |
1306 | } | 1351 | } |
1307 | 1352 | ||
1308 | /* If the QH is neither stopped nor finished unlinking (normal case), | 1353 | /* If the QH is neither stopped nor finished unlinking (normal case), |
1309 | * our work here is done. */ | 1354 | * our work here is done. */ |
1310 | restart: | 1355 | if (QH_FINISHED_UNLINKING(qh)) |
1311 | if (!(qh->is_stopped || QH_FINISHED_UNLINKING(qh))) | 1356 | qh->is_stopped = 1; |
1357 | else if (!qh->is_stopped) | ||
1312 | return; | 1358 | return; |
1313 | 1359 | ||
1314 | /* Otherwise give back each of the dequeued URBs */ | 1360 | /* Otherwise give back each of the dequeued URBs */ |
1361 | restart: | ||
1315 | list_for_each_entry(urbp, &qh->queue, node) { | 1362 | list_for_each_entry(urbp, &qh->queue, node) { |
1316 | urb = urbp->urb; | 1363 | urb = urbp->urb; |
1317 | if (urb->status != -EINPROGRESS) { | 1364 | if (urb->status != -EINPROGRESS) { |
1318 | uhci_save_toggle(qh, urb); | 1365 | |
1366 | /* Fix up the TD links and save the toggles for | ||
1367 | * non-Isochronous queues. For Isochronous queues, | ||
1368 | * test for too-recent dequeues. */ | ||
1369 | if (!uhci_cleanup_queue(uhci, qh, urb)) { | ||
1370 | qh->is_stopped = 0; | ||
1371 | return; | ||
1372 | } | ||
1319 | uhci_giveback_urb(uhci, qh, urb, regs); | 1373 | uhci_giveback_urb(uhci, qh, urb, regs); |
1320 | goto restart; | 1374 | goto restart; |
1321 | } | 1375 | } |
@@ -1327,6 +1381,18 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, | |||
1327 | if (!list_empty(&qh->queue)) { | 1381 | if (!list_empty(&qh->queue)) { |
1328 | if (qh->needs_fixup) | 1382 | if (qh->needs_fixup) |
1329 | uhci_fixup_toggles(qh, 0); | 1383 | uhci_fixup_toggles(qh, 0); |
1384 | |||
1385 | /* If the first URB on the queue wants FSBR but its time | ||
1386 | * limit has expired, set the next TD to interrupt on | ||
1387 | * completion before reactivating the QH. */ | ||
1388 | urbp = list_entry(qh->queue.next, struct urb_priv, node); | ||
1389 | if (urbp->fsbr && qh->wait_expired) { | ||
1390 | struct uhci_td *td = list_entry(urbp->td_list.next, | ||
1391 | struct uhci_td, list); | ||
1392 | |||
1393 | td->status |= __cpu_to_le32(TD_CTRL_IOC); | ||
1394 | } | ||
1395 | |||
1330 | uhci_activate_qh(uhci, qh); | 1396 | uhci_activate_qh(uhci, qh); |
1331 | } | 1397 | } |
1332 | 1398 | ||
@@ -1336,15 +1402,84 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, | |||
1336 | uhci_make_qh_idle(uhci, qh); | 1402 | uhci_make_qh_idle(uhci, qh); |
1337 | } | 1403 | } |
1338 | 1404 | ||
1339 | static void uhci_free_pending_tds(struct uhci_hcd *uhci) | 1405 | /* |
1406 | * Check for queues that have made some forward progress. | ||
1407 | * Returns 0 if the queue is not Isochronous, is ACTIVE, and | ||
1408 | * has not advanced since last examined; 1 otherwise. | ||
1409 | * | ||
1410 | * Early Intel controllers have a bug which causes qh->element sometimes | ||
1411 | * not to advance when a TD completes successfully. The queue remains | ||
1412 | * stuck on the inactive completed TD. We detect such cases and advance | ||
1413 | * the element pointer by hand. | ||
1414 | */ | ||
1415 | static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) | ||
1340 | { | 1416 | { |
1341 | struct uhci_td *td, *tmp; | 1417 | struct urb_priv *urbp = NULL; |
1418 | struct uhci_td *td; | ||
1419 | int ret = 1; | ||
1420 | unsigned status; | ||
1342 | 1421 | ||
1343 | list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) { | 1422 | if (qh->type == USB_ENDPOINT_XFER_ISOC) |
1344 | list_del_init(&td->remove_list); | 1423 | goto done; |
1345 | 1424 | ||
1346 | uhci_free_td(uhci, td); | 1425 | /* Treat an UNLINKING queue as though it hasn't advanced. |
1426 | * This is okay because reactivation will treat it as though | ||
1427 | * it has advanced, and if it is going to become IDLE then | ||
1428 | * this doesn't matter anyway. Furthermore it's possible | ||
1429 | * for an UNLINKING queue not to have any URBs at all, or | ||
1430 | * for its first URB not to have any TDs (if it was dequeued | ||
1431 | * just as it completed). So it's not easy in any case to | ||
1432 | * test whether such queues have advanced. */ | ||
1433 | if (qh->state != QH_STATE_ACTIVE) { | ||
1434 | urbp = NULL; | ||
1435 | status = 0; | ||
1436 | |||
1437 | } else { | ||
1438 | urbp = list_entry(qh->queue.next, struct urb_priv, node); | ||
1439 | td = list_entry(urbp->td_list.next, struct uhci_td, list); | ||
1440 | status = td_status(td); | ||
1441 | if (!(status & TD_CTRL_ACTIVE)) { | ||
1442 | |||
1443 | /* We're okay, the queue has advanced */ | ||
1444 | qh->wait_expired = 0; | ||
1445 | qh->advance_jiffies = jiffies; | ||
1446 | goto done; | ||
1447 | } | ||
1448 | ret = 0; | ||
1449 | } | ||
1450 | |||
1451 | /* The queue hasn't advanced; check for timeout */ | ||
1452 | if (qh->wait_expired) | ||
1453 | goto done; | ||
1454 | |||
1455 | if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) { | ||
1456 | |||
1457 | /* Detect the Intel bug and work around it */ | ||
1458 | if (qh->post_td && qh_element(qh) == | ||
1459 | cpu_to_le32(qh->post_td->dma_handle)) { | ||
1460 | qh->element = qh->post_td->link; | ||
1461 | qh->advance_jiffies = jiffies; | ||
1462 | ret = 1; | ||
1463 | goto done; | ||
1464 | } | ||
1465 | |||
1466 | qh->wait_expired = 1; | ||
1467 | |||
1468 | /* If the current URB wants FSBR, unlink it temporarily | ||
1469 | * so that we can safely set the next TD to interrupt on | ||
1470 | * completion. That way we'll know as soon as the queue | ||
1471 | * starts moving again. */ | ||
1472 | if (urbp && urbp->fsbr && !(status & TD_CTRL_IOC)) | ||
1473 | uhci_unlink_qh(uhci, qh); | ||
1474 | |||
1475 | } else { | ||
1476 | /* Unmoving but not-yet-expired queues keep FSBR alive */ | ||
1477 | if (urbp) | ||
1478 | uhci_urbp_wants_fsbr(uhci, urbp); | ||
1347 | } | 1479 | } |
1480 | |||
1481 | done: | ||
1482 | return ret; | ||
1348 | } | 1483 | } |
1349 | 1484 | ||
1350 | /* | 1485 | /* |
@@ -1361,14 +1496,13 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) | |||
1361 | return; | 1496 | return; |
1362 | } | 1497 | } |
1363 | uhci->scan_in_progress = 1; | 1498 | uhci->scan_in_progress = 1; |
1364 | rescan: | 1499 | rescan: |
1365 | uhci->need_rescan = 0; | 1500 | uhci->need_rescan = 0; |
1501 | uhci->fsbr_is_wanted = 0; | ||
1366 | 1502 | ||
1367 | uhci_clear_next_interrupt(uhci); | 1503 | uhci_clear_next_interrupt(uhci); |
1368 | uhci_get_current_frame_number(uhci); | 1504 | uhci_get_current_frame_number(uhci); |
1369 | 1505 | uhci->cur_iso_frame = uhci->frame_number; | |
1370 | if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) | ||
1371 | uhci_free_pending_tds(uhci); | ||
1372 | 1506 | ||
1373 | /* Go through all the QH queues and process the URBs in each one */ | 1507 | /* Go through all the QH queues and process the URBs in each one */ |
1374 | for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) { | 1508 | for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) { |
@@ -1377,33 +1511,30 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) | |||
1377 | while ((qh = uhci->next_qh) != uhci->skelqh[i]) { | 1511 | while ((qh = uhci->next_qh) != uhci->skelqh[i]) { |
1378 | uhci->next_qh = list_entry(qh->node.next, | 1512 | uhci->next_qh = list_entry(qh->node.next, |
1379 | struct uhci_qh, node); | 1513 | struct uhci_qh, node); |
1380 | uhci_scan_qh(uhci, qh, regs); | 1514 | |
1515 | if (uhci_advance_check(uhci, qh)) { | ||
1516 | uhci_scan_qh(uhci, qh, regs); | ||
1517 | if (qh->state == QH_STATE_ACTIVE) { | ||
1518 | uhci_urbp_wants_fsbr(uhci, | ||
1519 | list_entry(qh->queue.next, struct urb_priv, node)); | ||
1520 | } | ||
1521 | } | ||
1381 | } | 1522 | } |
1382 | } | 1523 | } |
1383 | 1524 | ||
1525 | uhci->last_iso_frame = uhci->cur_iso_frame; | ||
1384 | if (uhci->need_rescan) | 1526 | if (uhci->need_rescan) |
1385 | goto rescan; | 1527 | goto rescan; |
1386 | uhci->scan_in_progress = 0; | 1528 | uhci->scan_in_progress = 0; |
1387 | 1529 | ||
1388 | /* If the controller is stopped, we can finish these off right now */ | 1530 | if (uhci->fsbr_is_on && !uhci->fsbr_is_wanted && |
1389 | if (uhci->is_stopped) | 1531 | !uhci->fsbr_expiring) { |
1390 | uhci_free_pending_tds(uhci); | 1532 | uhci->fsbr_expiring = 1; |
1533 | mod_timer(&uhci->fsbr_timer, jiffies + FSBR_OFF_DELAY); | ||
1534 | } | ||
1391 | 1535 | ||
1392 | if (list_empty(&uhci->td_remove_list) && | 1536 | if (list_empty(&uhci->skel_unlink_qh->node)) |
1393 | list_empty(&uhci->skel_unlink_qh->node)) | ||
1394 | uhci_clear_next_interrupt(uhci); | 1537 | uhci_clear_next_interrupt(uhci); |
1395 | else | 1538 | else |
1396 | uhci_set_next_interrupt(uhci); | 1539 | uhci_set_next_interrupt(uhci); |
1397 | } | 1540 | } |
1398 | |||
1399 | static void check_fsbr(struct uhci_hcd *uhci) | ||
1400 | { | ||
1401 | /* For now, don't scan URBs for FSBR timeouts. | ||
1402 | * Add it back in later... */ | ||
1403 | |||
1404 | /* Really disable FSBR */ | ||
1405 | if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { | ||
1406 | uhci->fsbrtimeout = 0; | ||
1407 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | ||
1408 | } | ||
1409 | } | ||
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 2a0e18a48748..b2bafc37c414 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c | |||
@@ -513,7 +513,7 @@ static void mts_do_sg (struct urb* transfer, struct pt_regs *regs) | |||
513 | mts_transfer_cleanup(transfer); | 513 | mts_transfer_cleanup(transfer); |
514 | } | 514 | } |
515 | 515 | ||
516 | sg = context->srb->buffer; | 516 | sg = context->srb->request_buffer; |
517 | context->fragment++; | 517 | context->fragment++; |
518 | mts_int_submit_urb(transfer, | 518 | mts_int_submit_urb(transfer, |
519 | context->data_pipe, | 519 | context->data_pipe, |
@@ -549,19 +549,19 @@ mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc ) | |||
549 | desc->context.fragment = 0; | 549 | desc->context.fragment = 0; |
550 | 550 | ||
551 | if (!srb->use_sg) { | 551 | if (!srb->use_sg) { |
552 | if ( !srb->bufflen ){ | 552 | if ( !srb->request_bufflen ){ |
553 | desc->context.data = NULL; | 553 | desc->context.data = NULL; |
554 | desc->context.data_length = 0; | 554 | desc->context.data_length = 0; |
555 | return; | 555 | return; |
556 | } else { | 556 | } else { |
557 | desc->context.data = srb->buffer; | 557 | desc->context.data = srb->request_buffer; |
558 | desc->context.data_length = srb->bufflen; | 558 | desc->context.data_length = srb->request_bufflen; |
559 | MTS_DEBUG("length = %d or %d\n", | 559 | MTS_DEBUG("length = %d or %d\n", |
560 | srb->request_bufflen, srb->bufflen); | 560 | srb->request_bufflen, srb->bufflen); |
561 | } | 561 | } |
562 | } else { | 562 | } else { |
563 | MTS_DEBUG("Using scatter/gather\n"); | 563 | MTS_DEBUG("Using scatter/gather\n"); |
564 | sg = srb->buffer; | 564 | sg = srb->request_buffer; |
565 | desc->context.data = page_address(sg[0].page) + sg[0].offset; | 565 | desc->context.data = page_address(sg[0].page) + sg[0].offset; |
566 | desc->context.data_length = sg[0].length; | 566 | desc->context.data_length = sg[0].length; |
567 | } | 567 | } |
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c index df29b8078b54..18c10e150ef3 100644 --- a/drivers/usb/input/acecad.c +++ b/drivers/usb/input/acecad.c | |||
@@ -27,11 +27,9 @@ | |||
27 | 27 | ||
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/input.h> | ||
31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
32 | #include <linux/init.h> | 31 | #include <linux/init.h> |
33 | #include <linux/usb.h> | 32 | #include <linux/usb/input.h> |
34 | #include <linux/usb_input.h> | ||
35 | 33 | ||
36 | /* | 34 | /* |
37 | * Version Information | 35 | * Version Information |
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index a6693b0d1c4c..b138dae2b055 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c | |||
@@ -73,11 +73,9 @@ | |||
73 | #include <linux/jiffies.h> | 73 | #include <linux/jiffies.h> |
74 | #include <linux/kernel.h> | 74 | #include <linux/kernel.h> |
75 | #include <linux/slab.h> | 75 | #include <linux/slab.h> |
76 | #include <linux/input.h> | ||
77 | #include <linux/module.h> | 76 | #include <linux/module.h> |
78 | #include <linux/init.h> | 77 | #include <linux/init.h> |
79 | #include <linux/usb.h> | 78 | #include <linux/usb/input.h> |
80 | #include <linux/usb_input.h> | ||
81 | #include <linux/sched.h> | 79 | #include <linux/sched.h> |
82 | #include <asm/uaccess.h> | 80 | #include <asm/uaccess.h> |
83 | #include <asm/unaligned.h> | 81 | #include <asm/unaligned.h> |
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index c222ed13deab..36855062eacc 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Apple USB Touchpad (for post-February 2005 PowerBooks) driver | 2 | * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver |
3 | * | 3 | * |
4 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | 4 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) |
5 | * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) | 5 | * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) |
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) | 7 | * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) |
8 | * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) | 8 | * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) |
9 | * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) | 9 | * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) |
10 | * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) | ||
10 | * | 11 | * |
11 | * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. | 12 | * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. |
12 | * | 13 | * |
@@ -32,9 +33,7 @@ | |||
32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
33 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
34 | #include <linux/module.h> | 35 | #include <linux/module.h> |
35 | #include <linux/usb.h> | 36 | #include <linux/usb/input.h> |
36 | #include <linux/input.h> | ||
37 | #include <linux/usb_input.h> | ||
38 | 37 | ||
39 | /* Apple has powerbooks which have the keyboard with different Product IDs */ | 38 | /* Apple has powerbooks which have the keyboard with different Product IDs */ |
40 | #define APPLE_VENDOR_ID 0x05AC | 39 | #define APPLE_VENDOR_ID 0x05AC |
@@ -44,6 +43,11 @@ | |||
44 | #define GEYSER_ISO_PRODUCT_ID 0x0215 | 43 | #define GEYSER_ISO_PRODUCT_ID 0x0215 |
45 | #define GEYSER_JIS_PRODUCT_ID 0x0216 | 44 | #define GEYSER_JIS_PRODUCT_ID 0x0216 |
46 | 45 | ||
46 | /* MacBook devices */ | ||
47 | #define GEYSER3_ANSI_PRODUCT_ID 0x0217 | ||
48 | #define GEYSER3_ISO_PRODUCT_ID 0x0218 | ||
49 | #define GEYSER3_JIS_PRODUCT_ID 0x0219 | ||
50 | |||
47 | #define ATP_DEVICE(prod) \ | 51 | #define ATP_DEVICE(prod) \ |
48 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ | 52 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ |
49 | USB_DEVICE_ID_MATCH_INT_CLASS | \ | 53 | USB_DEVICE_ID_MATCH_INT_CLASS | \ |
@@ -65,6 +69,10 @@ static struct usb_device_id atp_table [] = { | |||
65 | { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, | 69 | { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, |
66 | { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, | 70 | { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, |
67 | 71 | ||
72 | { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) }, | ||
73 | { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) }, | ||
74 | { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) }, | ||
75 | |||
68 | /* Terminating entry */ | 76 | /* Terminating entry */ |
69 | { } | 77 | { } |
70 | }; | 78 | }; |
@@ -101,6 +109,13 @@ MODULE_DEVICE_TABLE (usb, atp_table); | |||
101 | */ | 109 | */ |
102 | #define ATP_THRESHOLD 5 | 110 | #define ATP_THRESHOLD 5 |
103 | 111 | ||
112 | /* MacBook Pro (Geyser 3) initialization constants */ | ||
113 | #define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 | ||
114 | #define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 | ||
115 | #define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 | ||
116 | #define ATP_GEYSER3_MODE_REQUEST_INDEX 0 | ||
117 | #define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04 | ||
118 | |||
104 | /* Structure to hold all of our device specific stuff */ | 119 | /* Structure to hold all of our device specific stuff */ |
105 | struct atp { | 120 | struct atp { |
106 | char phys[64]; | 121 | char phys[64]; |
@@ -147,13 +162,22 @@ MODULE_PARM_DESC(debug, "Activate debugging output"); | |||
147 | /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ | 162 | /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ |
148 | static inline int atp_is_geyser_2(struct atp *dev) | 163 | static inline int atp_is_geyser_2(struct atp *dev) |
149 | { | 164 | { |
150 | int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct); | 165 | u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); |
151 | 166 | ||
152 | return (productId == GEYSER_ANSI_PRODUCT_ID) || | 167 | return (productId == GEYSER_ANSI_PRODUCT_ID) || |
153 | (productId == GEYSER_ISO_PRODUCT_ID) || | 168 | (productId == GEYSER_ISO_PRODUCT_ID) || |
154 | (productId == GEYSER_JIS_PRODUCT_ID); | 169 | (productId == GEYSER_JIS_PRODUCT_ID); |
155 | } | 170 | } |
156 | 171 | ||
172 | static inline int atp_is_geyser_3(struct atp *dev) | ||
173 | { | ||
174 | u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); | ||
175 | |||
176 | return (productId == GEYSER3_ANSI_PRODUCT_ID) || | ||
177 | (productId == GEYSER3_ISO_PRODUCT_ID) || | ||
178 | (productId == GEYSER3_JIS_PRODUCT_ID); | ||
179 | } | ||
180 | |||
157 | static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, | 181 | static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, |
158 | int *z, int *fingers) | 182 | int *z, int *fingers) |
159 | { | 183 | { |
@@ -219,12 +243,33 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) | |||
219 | 243 | ||
220 | /* drop incomplete datasets */ | 244 | /* drop incomplete datasets */ |
221 | if (dev->urb->actual_length != dev->datalen) { | 245 | if (dev->urb->actual_length != dev->datalen) { |
222 | dprintk("appletouch: incomplete data package.\n"); | 246 | dprintk("appletouch: incomplete data package" |
247 | " (first byte: %d, length: %d).\n", | ||
248 | dev->data[0], dev->urb->actual_length); | ||
223 | goto exit; | 249 | goto exit; |
224 | } | 250 | } |
225 | 251 | ||
226 | /* reorder the sensors values */ | 252 | /* reorder the sensors values */ |
227 | if (atp_is_geyser_2(dev)) { | 253 | if (atp_is_geyser_3(dev)) { |
254 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | ||
255 | |||
256 | /* | ||
257 | * The values are laid out like this: | ||
258 | * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... | ||
259 | * '-' is an unused value. | ||
260 | */ | ||
261 | |||
262 | /* read X values */ | ||
263 | for (i = 0, j = 19; i < 20; i += 2, j += 3) { | ||
264 | dev->xy_cur[i] = dev->data[j + 1]; | ||
265 | dev->xy_cur[i + 1] = dev->data[j + 2]; | ||
266 | } | ||
267 | /* read Y values */ | ||
268 | for (i = 0, j = 1; i < 9; i += 2, j += 3) { | ||
269 | dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; | ||
270 | dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; | ||
271 | } | ||
272 | } else if (atp_is_geyser_2(dev)) { | ||
228 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | 273 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); |
229 | 274 | ||
230 | /* | 275 | /* |
@@ -267,6 +312,9 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) | |||
267 | dev->x_old = dev->y_old = -1; | 312 | dev->x_old = dev->y_old = -1; |
268 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | 313 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); |
269 | 314 | ||
315 | if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ | ||
316 | goto exit; | ||
317 | |||
270 | /* 17" Powerbooks have extra X sensors */ | 318 | /* 17" Powerbooks have extra X sensors */ |
271 | for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { | 319 | for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { |
272 | if (!dev->xy_cur[i]) continue; | 320 | if (!dev->xy_cur[i]) continue; |
@@ -414,7 +462,50 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id | |||
414 | dev->udev = udev; | 462 | dev->udev = udev; |
415 | dev->input = input_dev; | 463 | dev->input = input_dev; |
416 | dev->overflowwarn = 0; | 464 | dev->overflowwarn = 0; |
417 | dev->datalen = (atp_is_geyser_2(dev)?64:81); | 465 | if (atp_is_geyser_3(dev)) |
466 | dev->datalen = 64; | ||
467 | else if (atp_is_geyser_2(dev)) | ||
468 | dev->datalen = 64; | ||
469 | else | ||
470 | dev->datalen = 81; | ||
471 | |||
472 | if (atp_is_geyser_3(dev)) { | ||
473 | /* | ||
474 | * By default Geyser 3 device sends standard USB HID mouse | ||
475 | * packets (Report ID 2). This code changes device mode, so it | ||
476 | * sends raw sensor reports (Report ID 5). | ||
477 | */ | ||
478 | char data[8]; | ||
479 | int size; | ||
480 | |||
481 | size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
482 | ATP_GEYSER3_MODE_READ_REQUEST_ID, | ||
483 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
484 | ATP_GEYSER3_MODE_REQUEST_VALUE, | ||
485 | ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); | ||
486 | |||
487 | if (size != 8) { | ||
488 | err("Could not do mode read request from device" | ||
489 | " (Geyser 3 mode)"); | ||
490 | goto err_free_devs; | ||
491 | } | ||
492 | |||
493 | /* Apply the mode switch */ | ||
494 | data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE; | ||
495 | |||
496 | size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
497 | ATP_GEYSER3_MODE_WRITE_REQUEST_ID, | ||
498 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
499 | ATP_GEYSER3_MODE_REQUEST_VALUE, | ||
500 | ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); | ||
501 | |||
502 | if (size != 8) { | ||
503 | err("Could not do mode write request to device" | ||
504 | " (Geyser 3 mode)"); | ||
505 | goto err_free_devs; | ||
506 | } | ||
507 | printk("appletouch Geyser 3 inited.\n"); | ||
508 | } | ||
418 | 509 | ||
419 | dev->urb = usb_alloc_urb(0, GFP_KERNEL); | 510 | dev->urb = usb_alloc_urb(0, GFP_KERNEL); |
420 | if (!dev->urb) { | 511 | if (!dev->urb) { |
@@ -447,7 +538,15 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id | |||
447 | 538 | ||
448 | set_bit(EV_ABS, input_dev->evbit); | 539 | set_bit(EV_ABS, input_dev->evbit); |
449 | 540 | ||
450 | if (atp_is_geyser_2(dev)) { | 541 | if (atp_is_geyser_3(dev)) { |
542 | /* | ||
543 | * MacBook have 20 X sensors, 10 Y sensors | ||
544 | */ | ||
545 | input_set_abs_params(input_dev, ABS_X, 0, | ||
546 | ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); | ||
547 | input_set_abs_params(input_dev, ABS_Y, 0, | ||
548 | ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); | ||
549 | } else if (atp_is_geyser_2(dev)) { | ||
451 | /* | 550 | /* |
452 | * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected | 551 | * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected |
453 | * later. | 552 | * later. |
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 99f986cb6e95..07c8c0e665dd 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c | |||
@@ -92,9 +92,7 @@ | |||
92 | #include <linux/slab.h> | 92 | #include <linux/slab.h> |
93 | #include <linux/module.h> | 93 | #include <linux/module.h> |
94 | #include <linux/moduleparam.h> | 94 | #include <linux/moduleparam.h> |
95 | #include <linux/input.h> | 95 | #include <linux/usb/input.h> |
96 | #include <linux/usb.h> | ||
97 | #include <linux/usb_input.h> | ||
98 | #include <linux/wait.h> | 96 | #include <linux/wait.h> |
99 | #include <linux/jiffies.h> | 97 | #include <linux/jiffies.h> |
100 | 98 | ||
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c index ab1a1ae24be9..ea71de81ca6b 100644 --- a/drivers/usb/input/ati_remote2.c +++ b/drivers/usb/input/ati_remote2.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * as published by the Free Software Foundation. | 8 | * as published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/usb_input.h> | 11 | #include <linux/usb/input.h> |
12 | 12 | ||
13 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" | 13 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" |
14 | #define DRIVER_VERSION "0.1" | 14 | #define DRIVER_VERSION "0.1" |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 435273e7c85c..b9fb9687f926 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -944,21 +944,28 @@ static void hid_reset(void *_hid) | |||
944 | dev_dbg(&hid->intf->dev, "resetting device\n"); | 944 | dev_dbg(&hid->intf->dev, "resetting device\n"); |
945 | rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf); | 945 | rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf); |
946 | if (rc_lock >= 0) { | 946 | if (rc_lock >= 0) { |
947 | rc = usb_reset_device(hid->dev); | 947 | rc = usb_reset_composite_device(hid->dev, hid->intf); |
948 | if (rc_lock) | 948 | if (rc_lock) |
949 | usb_unlock_device(hid->dev); | 949 | usb_unlock_device(hid->dev); |
950 | } | 950 | } |
951 | clear_bit(HID_RESET_PENDING, &hid->iofl); | 951 | clear_bit(HID_RESET_PENDING, &hid->iofl); |
952 | 952 | ||
953 | if (rc == 0) { | 953 | switch (rc) { |
954 | hid->retry_delay = 0; | 954 | case 0: |
955 | if (hid_start_in(hid)) | 955 | if (!test_bit(HID_IN_RUNNING, &hid->iofl)) |
956 | hid_io_error(hid); | 956 | hid_io_error(hid); |
957 | } else if (!(rc == -ENODEV || rc == -EHOSTUNREACH || rc == -EINTR)) | 957 | break; |
958 | default: | ||
958 | err("can't reset device, %s-%s/input%d, status %d", | 959 | err("can't reset device, %s-%s/input%d, status %d", |
959 | hid->dev->bus->bus_name, | 960 | hid->dev->bus->bus_name, |
960 | hid->dev->devpath, | 961 | hid->dev->devpath, |
961 | hid->ifnum, rc); | 962 | hid->ifnum, rc); |
963 | /* FALLTHROUGH */ | ||
964 | case -EHOSTUNREACH: | ||
965 | case -ENODEV: | ||
966 | case -EINTR: | ||
967 | break; | ||
968 | } | ||
962 | } | 969 | } |
963 | 970 | ||
964 | /* Main I/O error handler */ | 971 | /* Main I/O error handler */ |
@@ -1374,9 +1381,6 @@ void hid_close(struct hid_device *hid) | |||
1374 | 1381 | ||
1375 | #define USB_VENDOR_ID_PANJIT 0x134c | 1382 | #define USB_VENDOR_ID_PANJIT 0x134c |
1376 | 1383 | ||
1377 | #define USB_VENDOR_ID_SILVERCREST 0x062a | ||
1378 | #define USB_DEVICE_ID_SILVERCREST_KB 0x0201 | ||
1379 | |||
1380 | /* | 1384 | /* |
1381 | * Initialize all reports | 1385 | * Initialize all reports |
1382 | */ | 1386 | */ |
@@ -1461,9 +1465,6 @@ void hid_init_reports(struct hid_device *hid) | |||
1461 | #define USB_VENDOR_ID_ONTRAK 0x0a07 | 1465 | #define USB_VENDOR_ID_ONTRAK 0x0a07 |
1462 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 | 1466 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 |
1463 | 1467 | ||
1464 | #define USB_VENDOR_ID_TANGTOP 0x0d3d | ||
1465 | #define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001 | ||
1466 | |||
1467 | #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f | 1468 | #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f |
1468 | #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 | 1469 | #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 |
1469 | 1470 | ||
@@ -1520,12 +1521,6 @@ void hid_init_reports(struct hid_device *hid) | |||
1520 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 | 1521 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 |
1521 | #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a | 1522 | #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a |
1522 | 1523 | ||
1523 | #define USB_VENDOR_ID_CHICONY 0x04f2 | ||
1524 | #define USB_DEVICE_ID_CHICONY_USBHUB_KB 0x0100 | ||
1525 | |||
1526 | #define USB_VENDOR_ID_BTC 0x046e | ||
1527 | #define USB_DEVICE_ID_BTC_KEYBOARD 0x5303 | ||
1528 | |||
1529 | #define USB_VENDOR_ID_VERNIER 0x08f7 | 1524 | #define USB_VENDOR_ID_VERNIER 0x08f7 |
1530 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | 1525 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 |
1531 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 | 1526 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 |
@@ -1549,20 +1544,13 @@ void hid_init_reports(struct hid_device *hid) | |||
1549 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 | 1544 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 |
1550 | 1545 | ||
1551 | #define USB_VENDOR_ID_APPLE 0x05ac | 1546 | #define USB_VENDOR_ID_APPLE 0x05ac |
1552 | #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 | 1547 | #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 |
1553 | 1548 | ||
1554 | #define USB_VENDOR_ID_CHERRY 0x046a | 1549 | #define USB_VENDOR_ID_CHERRY 0x046a |
1555 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | 1550 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 |
1556 | 1551 | ||
1557 | #define USB_VENDOR_ID_HP 0x03f0 | 1552 | #define USB_VENDOR_ID_YEALINK 0x6993 |
1558 | #define USB_DEVICE_ID_HP_USBHUB_KB 0x020c | 1553 | #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 |
1559 | |||
1560 | #define USB_VENDOR_ID_IBM 0x04b3 | ||
1561 | #define USB_DEVICE_ID_IBM_USBHUB_KB 0x3005 | ||
1562 | |||
1563 | #define USB_VENDOR_ID_CREATIVELABS 0x062a | ||
1564 | #define USB_DEVICE_ID_CREATIVELABS_SILVERCREST 0x0201 | ||
1565 | |||
1566 | /* | 1554 | /* |
1567 | * Alphabetically sorted blacklist by quirk type. | 1555 | * Alphabetically sorted blacklist by quirk type. |
1568 | */ | 1556 | */ |
@@ -1671,6 +1659,7 @@ static const struct hid_blacklist { | |||
1671 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE }, | 1659 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE }, |
1672 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | 1660 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, |
1673 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | 1661 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, |
1662 | { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, | ||
1674 | 1663 | ||
1675 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, | 1664 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, |
1676 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, | 1665 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, |
@@ -1680,16 +1669,9 @@ static const struct hid_blacklist { | |||
1680 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, | 1669 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, |
1681 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, | 1670 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, |
1682 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, | 1671 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, |
1683 | { USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET}, | ||
1684 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET}, | ||
1685 | { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVELABS_SILVERCREST, HID_QUIRK_NOGET }, | ||
1686 | { USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET }, | ||
1687 | { USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_USBHUB_KB, HID_QUIRK_NOGET }, | ||
1688 | { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, | ||
1689 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 1672 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
1690 | { USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET }, | ||
1691 | 1673 | ||
1692 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE }, | 1674 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, |
1693 | { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, | 1675 | { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, |
1694 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, | 1676 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, |
1695 | 1677 | ||
@@ -1711,6 +1693,9 @@ static const struct hid_blacklist { | |||
1711 | { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, | 1693 | { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, |
1712 | { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN }, | 1694 | { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN }, |
1713 | { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, | 1695 | { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, |
1696 | { USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1697 | { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1698 | { USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1714 | { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, | 1699 | { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, |
1715 | { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, | 1700 | { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, |
1716 | 1701 | ||
@@ -1794,6 +1779,14 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1794 | (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct))) | 1779 | (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct))) |
1795 | quirks = hid_blacklist[n].quirks; | 1780 | quirks = hid_blacklist[n].quirks; |
1796 | 1781 | ||
1782 | /* Many keyboards and mice don't like to be polled for reports, | ||
1783 | * so we will always set the HID_QUIRK_NOGET flag for them. */ | ||
1784 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { | ||
1785 | if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD || | ||
1786 | interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) | ||
1787 | quirks |= HID_QUIRK_NOGET; | ||
1788 | } | ||
1789 | |||
1797 | if (quirks & HID_QUIRK_IGNORE) | 1790 | if (quirks & HID_QUIRK_IGNORE) |
1798 | return NULL; | 1791 | return NULL; |
1799 | 1792 | ||
@@ -2080,11 +2073,29 @@ static int hid_resume(struct usb_interface *intf) | |||
2080 | int status; | 2073 | int status; |
2081 | 2074 | ||
2082 | clear_bit(HID_SUSPENDED, &hid->iofl); | 2075 | clear_bit(HID_SUSPENDED, &hid->iofl); |
2076 | hid->retry_delay = 0; | ||
2083 | status = hid_start_in(hid); | 2077 | status = hid_start_in(hid); |
2084 | dev_dbg(&intf->dev, "resume status %d\n", status); | 2078 | dev_dbg(&intf->dev, "resume status %d\n", status); |
2085 | return status; | 2079 | return status; |
2086 | } | 2080 | } |
2087 | 2081 | ||
2082 | /* Treat USB reset pretty much the same as suspend/resume */ | ||
2083 | static void hid_pre_reset(struct usb_interface *intf) | ||
2084 | { | ||
2085 | /* FIXME: What if the interface is already suspended? */ | ||
2086 | hid_suspend(intf, PMSG_ON); | ||
2087 | } | ||
2088 | |||
2089 | static void hid_post_reset(struct usb_interface *intf) | ||
2090 | { | ||
2091 | struct usb_device *dev = interface_to_usbdev (intf); | ||
2092 | |||
2093 | hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); | ||
2094 | /* FIXME: Any more reinitialization needed? */ | ||
2095 | |||
2096 | hid_resume(intf); | ||
2097 | } | ||
2098 | |||
2088 | static struct usb_device_id hid_usb_ids [] = { | 2099 | static struct usb_device_id hid_usb_ids [] = { |
2089 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, | 2100 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, |
2090 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, | 2101 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, |
@@ -2099,6 +2110,8 @@ static struct usb_driver hid_driver = { | |||
2099 | .disconnect = hid_disconnect, | 2110 | .disconnect = hid_disconnect, |
2100 | .suspend = hid_suspend, | 2111 | .suspend = hid_suspend, |
2101 | .resume = hid_resume, | 2112 | .resume = hid_resume, |
2113 | .pre_reset = hid_pre_reset, | ||
2114 | .post_reset = hid_post_reset, | ||
2102 | .id_table = hid_usb_ids, | 2115 | .id_table = hid_usb_ids, |
2103 | }; | 2116 | }; |
2104 | 2117 | ||
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 25bc85f8ce39..028e1ad89f5d 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c | |||
@@ -29,9 +29,7 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/input.h> | 32 | #include <linux/usb/input.h> |
33 | #include <linux/usb.h> | ||
34 | #include <linux/usb_input.h> | ||
35 | 33 | ||
36 | #undef DEBUG | 34 | #undef DEBUG |
37 | 35 | ||
@@ -567,16 +565,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
567 | break; | 565 | break; |
568 | } | 566 | } |
569 | 567 | ||
570 | set_bit(usage->type, input->evbit); | 568 | if (device->quirks & HID_QUIRK_MIGHTYMOUSE) { |
571 | 569 | if (usage->hid == HID_GD_Z) | |
572 | while (usage->code <= max && test_and_set_bit(usage->code, bit)) | 570 | map_rel(REL_HWHEEL); |
573 | usage->code = find_next_zero_bit(bit, max + 1, usage->code); | 571 | else if (usage->code == BTN_1) |
574 | 572 | map_key(BTN_2); | |
575 | if (usage->code > max) | 573 | else if (usage->code == BTN_2) |
576 | goto ignore; | 574 | map_key(BTN_1); |
577 | 575 | } | |
578 | if (((device->quirks & (HID_QUIRK_2WHEEL_POWERMOUSE)) && (usage->hid == 0x00010032))) | ||
579 | map_rel(REL_HWHEEL); | ||
580 | 576 | ||
581 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && | 577 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && |
582 | (usage->type == EV_REL) && (usage->code == REL_WHEEL)) | 578 | (usage->type == EV_REL) && (usage->code == REL_WHEEL)) |
@@ -586,6 +582,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
586 | || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) | 582 | || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) |
587 | goto ignore; | 583 | goto ignore; |
588 | 584 | ||
585 | set_bit(usage->type, input->evbit); | ||
586 | |||
587 | while (usage->code <= max && test_and_set_bit(usage->code, bit)) | ||
588 | usage->code = find_next_zero_bit(bit, max + 1, usage->code); | ||
589 | |||
590 | if (usage->code > max) | ||
591 | goto ignore; | ||
592 | |||
593 | |||
589 | if (usage->type == EV_ABS) { | 594 | if (usage->type == EV_ABS) { |
590 | 595 | ||
591 | int a = field->logical_minimum; | 596 | int a = field->logical_minimum; |
@@ -647,6 +652,11 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
647 | return; | 652 | return; |
648 | } | 653 | } |
649 | 654 | ||
655 | if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) { | ||
656 | input_event(input, usage->type, usage->code, -value); | ||
657 | return; | ||
658 | } | ||
659 | |||
650 | if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { | 660 | if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { |
651 | input_event(input, usage->type, REL_HWHEEL, value); | 661 | input_event(input, usage->type, REL_HWHEEL, value); |
652 | return; | 662 | return; |
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 9c62837b5b89..778e575de352 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h | |||
@@ -41,6 +41,14 @@ | |||
41 | #define USB_INTERFACE_CLASS_HID 3 | 41 | #define USB_INTERFACE_CLASS_HID 3 |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * USB HID interface subclass and protocol codes | ||
45 | */ | ||
46 | |||
47 | #define USB_INTERFACE_SUBCLASS_BOOT 1 | ||
48 | #define USB_INTERFACE_PROTOCOL_KEYBOARD 1 | ||
49 | #define USB_INTERFACE_PROTOCOL_MOUSE 2 | ||
50 | |||
51 | /* | ||
44 | * HID class requests | 52 | * HID class requests |
45 | */ | 53 | */ |
46 | 54 | ||
@@ -247,10 +255,11 @@ struct hid_item { | |||
247 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 | 255 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 |
248 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 | 256 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 |
249 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 | 257 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 |
250 | #define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400 | 258 | #define HID_QUIRK_MIGHTYMOUSE 0x00000400 |
251 | #define HID_QUIRK_CYMOTION 0x00000800 | 259 | #define HID_QUIRK_CYMOTION 0x00000800 |
252 | #define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 | 260 | #define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 |
253 | #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 | 261 | #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 |
262 | #define HID_QUIRK_INVERT_HWHEEL 0x00004000 | ||
254 | 263 | ||
255 | /* | 264 | /* |
256 | * This is the global environment of the parser. This information is | 265 | * This is the global environment of the parser. This information is |
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c index 7618ae5c104f..5c570cc703f3 100644 --- a/drivers/usb/input/itmtouch.c +++ b/drivers/usb/input/itmtouch.c | |||
@@ -42,11 +42,9 @@ | |||
42 | #include <linux/config.h> | 42 | #include <linux/config.h> |
43 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/input.h> | ||
46 | #include <linux/module.h> | 45 | #include <linux/module.h> |
47 | #include <linux/init.h> | 46 | #include <linux/init.h> |
48 | #include <linux/usb.h> | 47 | #include <linux/usb/input.h> |
49 | #include <linux/usb_input.h> | ||
50 | 48 | ||
51 | /* only an 8 byte buffer necessary for a single packet */ | 49 | /* only an 8 byte buffer necessary for a single packet */ |
52 | #define ITM_BUFSIZE 8 | 50 | #define ITM_BUFSIZE 8 |
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index f6d5cead542b..604ade356ead 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c | |||
@@ -1,12 +1,9 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/slab.h> | 2 | #include <linux/slab.h> |
3 | #include <linux/input.h> | ||
4 | #include <linux/module.h> | 3 | #include <linux/module.h> |
5 | #include <linux/init.h> | 4 | #include <linux/init.h> |
6 | #include <linux/usb.h> | 5 | #include <linux/usb/input.h> |
7 | #include <linux/usb_input.h> | ||
8 | #include <asm/unaligned.h> | 6 | #include <asm/unaligned.h> |
9 | #include <asm/byteorder.h> | ||
10 | 7 | ||
11 | /* | 8 | /* |
12 | * Version Information | 9 | * Version Information |
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c index 3d911976f378..70af985b5db9 100644 --- a/drivers/usb/input/keyspan_remote.c +++ b/drivers/usb/input/keyspan_remote.c | |||
@@ -18,9 +18,7 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
21 | #include <linux/input.h> | 21 | #include <linux/usb/input.h> |
22 | #include <linux/usb.h> | ||
23 | #include <linux/usb_input.h> | ||
24 | 22 | ||
25 | #define DRIVER_VERSION "v0.1" | 23 | #define DRIVER_VERSION "v0.1" |
26 | #define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>" | 24 | #define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>" |
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index f018953a5485..4fdee4db0729 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c | |||
@@ -42,11 +42,9 @@ | |||
42 | #include <linux/config.h> | 42 | #include <linux/config.h> |
43 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/input.h> | ||
46 | #include <linux/module.h> | 45 | #include <linux/module.h> |
47 | #include <linux/init.h> | 46 | #include <linux/init.h> |
48 | #include <linux/usb.h> | 47 | #include <linux/usb/input.h> |
49 | #include <linux/usb_input.h> | ||
50 | 48 | ||
51 | #define MTOUCHUSB_MIN_XC 0x0 | 49 | #define MTOUCHUSB_MIN_XC 0x0 |
52 | #define MTOUCHUSB_MAX_RAW_XC 0x4000 | 50 | #define MTOUCHUSB_MAX_RAW_XC 0x4000 |
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index fdf0f788062c..b3c0d0c3eae9 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c | |||
@@ -30,12 +30,10 @@ | |||
30 | 30 | ||
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/input.h> | ||
34 | #include <linux/module.h> | 33 | #include <linux/module.h> |
35 | #include <linux/init.h> | 34 | #include <linux/init.h> |
36 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
37 | #include <linux/usb.h> | 36 | #include <linux/usb/input.h> |
38 | #include <linux/usb_input.h> | ||
39 | 37 | ||
40 | #define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ | 38 | #define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ |
41 | #define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ | 39 | #define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ |
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index 697c5e573a11..da7b0bf51aff 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c | |||
@@ -27,11 +27,9 @@ | |||
27 | #include <linux/config.h> | 27 | #include <linux/config.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/input.h> | ||
31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
32 | #include <linux/init.h> | 31 | #include <linux/init.h> |
33 | #include <linux/usb.h> | 32 | #include <linux/usb/input.h> |
34 | #include <linux/usb_input.h> | ||
35 | 33 | ||
36 | #define TOUCHKIT_MIN_XC 0x0 | 34 | #define TOUCHKIT_MIN_XC 0x0 |
37 | #define TOUCHKIT_MAX_XC 0x07ff | 35 | #define TOUCHKIT_MAX_XC 0x07ff |
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index 2f3edc26cb50..5067a6ae650f 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c | |||
@@ -29,10 +29,8 @@ | |||
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/input.h> | ||
33 | #include <linux/init.h> | 32 | #include <linux/init.h> |
34 | #include <linux/usb.h> | 33 | #include <linux/usb/input.h> |
35 | #include <linux/usb_input.h> | ||
36 | 34 | ||
37 | /* | 35 | /* |
38 | * Version Information | 36 | * Version Information |
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index af526135d210..446935b671d9 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c | |||
@@ -28,11 +28,9 @@ | |||
28 | 28 | ||
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/input.h> | ||
32 | #include <linux/module.h> | 31 | #include <linux/module.h> |
33 | #include <linux/init.h> | 32 | #include <linux/init.h> |
34 | #include <linux/usb.h> | 33 | #include <linux/usb/input.h> |
35 | #include <linux/usb_input.h> | ||
36 | 34 | ||
37 | /* | 35 | /* |
38 | * Version Information | 36 | * Version Information |
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c index e9a07c1e905b..3b175aa482cd 100644 --- a/drivers/usb/input/usbtouchscreen.c +++ b/drivers/usb/input/usbtouchscreen.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/usb.h> | 41 | #include <linux/usb.h> |
42 | #include <linux/usb_input.h> | 42 | #include <linux/usb/input.h> |
43 | 43 | ||
44 | 44 | ||
45 | #define DRIVER_VERSION "v0.3" | 45 | #define DRIVER_VERSION "v0.3" |
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index cf84c6096f29..369461a70b72 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c | |||
@@ -69,13 +69,10 @@ | |||
69 | 69 | ||
70 | #include <linux/kernel.h> | 70 | #include <linux/kernel.h> |
71 | #include <linux/slab.h> | 71 | #include <linux/slab.h> |
72 | #include <linux/input.h> | ||
73 | #include <linux/module.h> | 72 | #include <linux/module.h> |
74 | #include <linux/init.h> | 73 | #include <linux/init.h> |
75 | #include <linux/usb.h> | 74 | #include <linux/usb/input.h> |
76 | #include <linux/usb_input.h> | ||
77 | #include <asm/unaligned.h> | 75 | #include <asm/unaligned.h> |
78 | #include <asm/byteorder.h> | ||
79 | 76 | ||
80 | /* | 77 | /* |
81 | * Version Information | 78 | * Version Information |
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index e278489a80c6..cfd4a4e04334 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c | |||
@@ -56,13 +56,11 @@ | |||
56 | 56 | ||
57 | #include <linux/config.h> | 57 | #include <linux/config.h> |
58 | #include <linux/kernel.h> | 58 | #include <linux/kernel.h> |
59 | #include <linux/input.h> | ||
60 | #include <linux/init.h> | 59 | #include <linux/init.h> |
61 | #include <linux/slab.h> | 60 | #include <linux/slab.h> |
62 | #include <linux/module.h> | 61 | #include <linux/module.h> |
63 | #include <linux/smp_lock.h> | 62 | #include <linux/smp_lock.h> |
64 | #include <linux/usb.h> | 63 | #include <linux/usb/input.h> |
65 | #include <linux/usb_input.h> | ||
66 | 64 | ||
67 | #define DRIVER_VERSION "v0.0.5" | 65 | #define DRIVER_VERSION "v0.0.5" |
68 | #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" | 66 | #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" |
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c index 37d2f0ba0319..24aedbb20f03 100644 --- a/drivers/usb/input/yealink.c +++ b/drivers/usb/input/yealink.c | |||
@@ -48,13 +48,11 @@ | |||
48 | 48 | ||
49 | #include <linux/config.h> | 49 | #include <linux/config.h> |
50 | #include <linux/kernel.h> | 50 | #include <linux/kernel.h> |
51 | #include <linux/input.h> | ||
52 | #include <linux/init.h> | 51 | #include <linux/init.h> |
53 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
54 | #include <linux/module.h> | 53 | #include <linux/module.h> |
55 | #include <linux/rwsem.h> | 54 | #include <linux/rwsem.h> |
56 | #include <linux/usb.h> | 55 | #include <linux/usb/input.h> |
57 | #include <linux/usb_input.h> | ||
58 | 56 | ||
59 | #include "map_to_7segment.h" | 57 | #include "map_to_7segment.h" |
60 | #include "yealink.h" | 58 | #include "yealink.h" |
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 8ba6a701e9c1..daa486dde8cf 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig | |||
@@ -88,6 +88,20 @@ config USB_LED | |||
88 | To compile this driver as a module, choose M here: the | 88 | To compile this driver as a module, choose M here: the |
89 | module will be called usbled. | 89 | module will be called usbled. |
90 | 90 | ||
91 | config USB_CY7C63 | ||
92 | tristate "Cypress CY7C63xxx USB driver support" | ||
93 | depends on USB | ||
94 | help | ||
95 | Say Y here if you want to connect a Cypress CY7C63xxx | ||
96 | micro controller to your computer's USB port. This driver | ||
97 | supports the pre-programmed devices (incl. firmware) by | ||
98 | AK Modul-Bus Computer GmbH. | ||
99 | |||
100 | Please see: http://www.ak-modul-bus.de/stat/mikrocontroller.html | ||
101 | |||
102 | To compile this driver as a module, choose M here: the | ||
103 | module will be called cy7c63. | ||
104 | |||
91 | config USB_CYTHERM | 105 | config USB_CYTHERM |
92 | tristate "Cypress USB thermometer driver support" | 106 | tristate "Cypress USB thermometer driver support" |
93 | depends on USB | 107 | depends on USB |
@@ -137,6 +151,15 @@ config USB_IDMOUSE | |||
137 | 151 | ||
138 | See also <http://www.fs.tum.de/~echtler/idmouse/>. | 152 | See also <http://www.fs.tum.de/~echtler/idmouse/>. |
139 | 153 | ||
154 | config USB_APPLEDISPLAY | ||
155 | tristate "Apple Cinema Display support" | ||
156 | depends on USB | ||
157 | select BACKLIGHT_LCD_SUPPORT | ||
158 | select BACKLIGHT_CLASS_DEVICE | ||
159 | help | ||
160 | Say Y here if you want to control the backlight of Apple Cinema | ||
161 | Displays over USB. This driver provides a sysfs interface. | ||
162 | |||
140 | source "drivers/usb/misc/sisusbvga/Kconfig" | 163 | source "drivers/usb/misc/sisusbvga/Kconfig" |
141 | 164 | ||
142 | config USB_LD | 165 | config USB_LD |
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 6c693bc68e2e..f25a97227297 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | obj-$(CONFIG_USB_AUERSWALD) += auerswald.o | 6 | obj-$(CONFIG_USB_AUERSWALD) += auerswald.o |
7 | obj-$(CONFIG_USB_CY7C63) += cy7c63.o | ||
7 | obj-$(CONFIG_USB_CYTHERM) += cytherm.o | 8 | obj-$(CONFIG_USB_CYTHERM) += cytherm.o |
8 | obj-$(CONFIG_USB_EMI26) += emi26.o | 9 | obj-$(CONFIG_USB_EMI26) += emi26.o |
9 | obj-$(CONFIG_USB_EMI62) += emi62.o | 10 | obj-$(CONFIG_USB_EMI62) += emi62.o |
@@ -17,6 +18,7 @@ obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o | |||
17 | obj-$(CONFIG_USB_RIO500) += rio500.o | 18 | obj-$(CONFIG_USB_RIO500) += rio500.o |
18 | obj-$(CONFIG_USB_TEST) += usbtest.o | 19 | obj-$(CONFIG_USB_TEST) += usbtest.o |
19 | obj-$(CONFIG_USB_USS720) += uss720.o | 20 | obj-$(CONFIG_USB_USS720) += uss720.o |
21 | obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o | ||
20 | 22 | ||
21 | obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ | 23 | obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ |
22 | 24 | ||
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c new file mode 100644 index 000000000000..bfde82f5d180 --- /dev/null +++ b/drivers/usb/misc/appledisplay.c | |||
@@ -0,0 +1,383 @@ | |||
1 | /* | ||
2 | * Apple Cinema Display driver | ||
3 | * | ||
4 | * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch) | ||
5 | * | ||
6 | * Thanks to Caskey L. Dickson for his work with acdctl. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/usb.h> | ||
29 | #include <linux/backlight.h> | ||
30 | #include <linux/timer.h> | ||
31 | #include <linux/workqueue.h> | ||
32 | #include <asm/atomic.h> | ||
33 | #include <asm/semaphore.h> | ||
34 | |||
35 | #define APPLE_VENDOR_ID 0x05AC | ||
36 | |||
37 | #define USB_REQ_GET_REPORT 0x01 | ||
38 | #define USB_REQ_SET_REPORT 0x09 | ||
39 | |||
40 | #define ACD_USB_TIMEOUT 250 | ||
41 | |||
42 | #define ACD_USB_EDID 0x0302 | ||
43 | #define ACD_USB_BRIGHTNESS 0x0310 | ||
44 | |||
45 | #define ACD_BTN_NONE 0 | ||
46 | #define ACD_BTN_BRIGHT_UP 3 | ||
47 | #define ACD_BTN_BRIGHT_DOWN 4 | ||
48 | |||
49 | #define ACD_URB_BUFFER_LEN 2 | ||
50 | #define ACD_MSG_BUFFER_LEN 2 | ||
51 | |||
52 | #define APPLEDISPLAY_DEVICE(prod) \ | ||
53 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ | ||
54 | USB_DEVICE_ID_MATCH_INT_CLASS | \ | ||
55 | USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ | ||
56 | .idVendor = APPLE_VENDOR_ID, \ | ||
57 | .idProduct = (prod), \ | ||
58 | .bInterfaceClass = USB_CLASS_HID, \ | ||
59 | .bInterfaceProtocol = 0x00 | ||
60 | |||
61 | /* table of devices that work with this driver */ | ||
62 | static struct usb_device_id appledisplay_table [] = { | ||
63 | { APPLEDISPLAY_DEVICE(0x9218) }, | ||
64 | { APPLEDISPLAY_DEVICE(0x9219) }, | ||
65 | { APPLEDISPLAY_DEVICE(0x921d) }, | ||
66 | |||
67 | /* Terminating entry */ | ||
68 | { } | ||
69 | }; | ||
70 | MODULE_DEVICE_TABLE(usb, appledisplay_table); | ||
71 | |||
72 | /* Structure to hold all of our device specific stuff */ | ||
73 | struct appledisplay { | ||
74 | struct usb_device *udev; /* usb device */ | ||
75 | struct urb *urb; /* usb request block */ | ||
76 | struct backlight_device *bd; /* backlight device */ | ||
77 | char *urbdata; /* interrupt URB data buffer */ | ||
78 | char *msgdata; /* control message data buffer */ | ||
79 | |||
80 | struct work_struct work; | ||
81 | int button_pressed; | ||
82 | spinlock_t lock; | ||
83 | }; | ||
84 | |||
85 | static atomic_t count_displays = ATOMIC_INIT(0); | ||
86 | static struct workqueue_struct *wq; | ||
87 | |||
88 | static void appledisplay_complete(struct urb *urb, struct pt_regs *regs) | ||
89 | { | ||
90 | struct appledisplay *pdata = urb->context; | ||
91 | unsigned long flags; | ||
92 | int retval; | ||
93 | |||
94 | switch (urb->status) { | ||
95 | case 0: | ||
96 | /* success */ | ||
97 | break; | ||
98 | case -EOVERFLOW: | ||
99 | printk(KERN_ERR "appletouch: OVERFLOW with data " | ||
100 | "length %d, actual length is %d\n", | ||
101 | ACD_URB_BUFFER_LEN, pdata->urb->actual_length); | ||
102 | case -ECONNRESET: | ||
103 | case -ENOENT: | ||
104 | case -ESHUTDOWN: | ||
105 | /* This urb is terminated, clean up */ | ||
106 | dbg("%s - urb shutting down with status: %d", | ||
107 | __FUNCTION__, urb->status); | ||
108 | return; | ||
109 | default: | ||
110 | dbg("%s - nonzero urb status received: %d", | ||
111 | __FUNCTION__, urb->status); | ||
112 | goto exit; | ||
113 | } | ||
114 | |||
115 | spin_lock_irqsave(&pdata->lock, flags); | ||
116 | |||
117 | switch(pdata->urbdata[1]) { | ||
118 | case ACD_BTN_BRIGHT_UP: | ||
119 | case ACD_BTN_BRIGHT_DOWN: | ||
120 | pdata->button_pressed = 1; | ||
121 | queue_work(wq, &pdata->work); | ||
122 | break; | ||
123 | case ACD_BTN_NONE: | ||
124 | default: | ||
125 | pdata->button_pressed = 0; | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | spin_unlock_irqrestore(&pdata->lock, flags); | ||
130 | |||
131 | exit: | ||
132 | retval = usb_submit_urb(pdata->urb, GFP_ATOMIC); | ||
133 | if (retval) { | ||
134 | err("%s - usb_submit_urb failed with result %d", | ||
135 | __FUNCTION__, retval); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static int appledisplay_bl_update_status(struct backlight_device *bd) | ||
140 | { | ||
141 | struct appledisplay *pdata = class_get_devdata(&bd->class_dev); | ||
142 | int retval; | ||
143 | |||
144 | pdata->msgdata[0] = 0x10; | ||
145 | pdata->msgdata[1] = bd->props->brightness; | ||
146 | |||
147 | retval = usb_control_msg( | ||
148 | pdata->udev, | ||
149 | usb_sndctrlpipe(pdata->udev, 0), | ||
150 | USB_REQ_SET_REPORT, | ||
151 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
152 | ACD_USB_BRIGHTNESS, | ||
153 | 0, | ||
154 | pdata->msgdata, 2, | ||
155 | ACD_USB_TIMEOUT); | ||
156 | |||
157 | return retval; | ||
158 | } | ||
159 | |||
160 | static int appledisplay_bl_get_brightness(struct backlight_device *bd) | ||
161 | { | ||
162 | struct appledisplay *pdata = class_get_devdata(&bd->class_dev); | ||
163 | int retval; | ||
164 | |||
165 | retval = usb_control_msg( | ||
166 | pdata->udev, | ||
167 | usb_rcvctrlpipe(pdata->udev, 0), | ||
168 | USB_REQ_GET_REPORT, | ||
169 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
170 | ACD_USB_BRIGHTNESS, | ||
171 | 0, | ||
172 | pdata->msgdata, 2, | ||
173 | ACD_USB_TIMEOUT); | ||
174 | |||
175 | if (retval < 0) | ||
176 | return retval; | ||
177 | else | ||
178 | return pdata->msgdata[1]; | ||
179 | } | ||
180 | |||
181 | static struct backlight_properties appledisplay_bl_data = { | ||
182 | .owner = THIS_MODULE, | ||
183 | .get_brightness = appledisplay_bl_get_brightness, | ||
184 | .update_status = appledisplay_bl_update_status, | ||
185 | .max_brightness = 0xFF | ||
186 | }; | ||
187 | |||
188 | static void appledisplay_work(void *private) | ||
189 | { | ||
190 | struct appledisplay *pdata = private; | ||
191 | int retval; | ||
192 | |||
193 | up(&pdata->bd->sem); | ||
194 | retval = appledisplay_bl_get_brightness(pdata->bd); | ||
195 | if (retval >= 0) | ||
196 | pdata->bd->props->brightness = retval; | ||
197 | down(&pdata->bd->sem); | ||
198 | |||
199 | /* Poll again in about 125ms if there's still a button pressed */ | ||
200 | if (pdata->button_pressed) | ||
201 | schedule_delayed_work(&pdata->work, HZ / 8); | ||
202 | } | ||
203 | |||
204 | static int appledisplay_probe(struct usb_interface *iface, | ||
205 | const struct usb_device_id *id) | ||
206 | { | ||
207 | struct appledisplay *pdata; | ||
208 | struct usb_device *udev = interface_to_usbdev(iface); | ||
209 | struct usb_host_interface *iface_desc; | ||
210 | struct usb_endpoint_descriptor *endpoint; | ||
211 | int int_in_endpointAddr = 0; | ||
212 | int i, retval = -ENOMEM, brightness; | ||
213 | char bl_name[20]; | ||
214 | |||
215 | /* set up the endpoint information */ | ||
216 | /* use only the first interrupt-in endpoint */ | ||
217 | iface_desc = iface->cur_altsetting; | ||
218 | for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { | ||
219 | endpoint = &iface_desc->endpoint[i].desc; | ||
220 | if (!int_in_endpointAddr && | ||
221 | (endpoint->bEndpointAddress & USB_DIR_IN) && | ||
222 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
223 | USB_ENDPOINT_XFER_INT)) { | ||
224 | /* we found an interrupt in endpoint */ | ||
225 | int_in_endpointAddr = endpoint->bEndpointAddress; | ||
226 | break; | ||
227 | } | ||
228 | } | ||
229 | if (!int_in_endpointAddr) { | ||
230 | err("Could not find int-in endpoint"); | ||
231 | return -EIO; | ||
232 | } | ||
233 | |||
234 | /* allocate memory for our device state and initialize it */ | ||
235 | pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL); | ||
236 | if (!pdata) { | ||
237 | retval = -ENOMEM; | ||
238 | err("Out of memory"); | ||
239 | goto error; | ||
240 | } | ||
241 | |||
242 | pdata->udev = udev; | ||
243 | |||
244 | spin_lock_init(&pdata->lock); | ||
245 | INIT_WORK(&pdata->work, appledisplay_work, pdata); | ||
246 | |||
247 | /* Allocate buffer for control messages */ | ||
248 | pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL); | ||
249 | if (!pdata->msgdata) { | ||
250 | retval = -ENOMEM; | ||
251 | err("appledisplay: Allocating buffer for control messages " | ||
252 | "failed"); | ||
253 | goto error; | ||
254 | } | ||
255 | |||
256 | /* Allocate interrupt URB */ | ||
257 | pdata->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
258 | if (!pdata->urb) { | ||
259 | retval = -ENOMEM; | ||
260 | err("appledisplay: Allocating URB failed"); | ||
261 | goto error; | ||
262 | } | ||
263 | |||
264 | /* Allocate buffer for interrupt data */ | ||
265 | pdata->urbdata = usb_buffer_alloc(pdata->udev, ACD_URB_BUFFER_LEN, | ||
266 | GFP_KERNEL, &pdata->urb->transfer_dma); | ||
267 | if (!pdata->urbdata) { | ||
268 | retval = -ENOMEM; | ||
269 | err("appledisplay: Allocating URB buffer failed"); | ||
270 | goto error; | ||
271 | } | ||
272 | |||
273 | /* Configure interrupt URB */ | ||
274 | usb_fill_int_urb(pdata->urb, udev, | ||
275 | usb_rcvintpipe(udev, int_in_endpointAddr), | ||
276 | pdata->urbdata, ACD_URB_BUFFER_LEN, appledisplay_complete, | ||
277 | pdata, 1); | ||
278 | if (usb_submit_urb(pdata->urb, GFP_KERNEL)) { | ||
279 | retval = -EIO; | ||
280 | err("appledisplay: Submitting URB failed"); | ||
281 | goto error; | ||
282 | } | ||
283 | |||
284 | /* Register backlight device */ | ||
285 | snprintf(bl_name, sizeof(bl_name), "appledisplay%d", | ||
286 | atomic_inc_return(&count_displays) - 1); | ||
287 | pdata->bd = backlight_device_register(bl_name, pdata, | ||
288 | &appledisplay_bl_data); | ||
289 | if (IS_ERR(pdata->bd)) { | ||
290 | err("appledisplay: Backlight registration failed"); | ||
291 | goto error; | ||
292 | } | ||
293 | |||
294 | /* Try to get brightness */ | ||
295 | up(&pdata->bd->sem); | ||
296 | brightness = appledisplay_bl_get_brightness(pdata->bd); | ||
297 | down(&pdata->bd->sem); | ||
298 | |||
299 | if (brightness < 0) { | ||
300 | retval = brightness; | ||
301 | err("appledisplay: Error while getting initial brightness: %d", retval); | ||
302 | goto error; | ||
303 | } | ||
304 | |||
305 | /* Set brightness in backlight device */ | ||
306 | up(&pdata->bd->sem); | ||
307 | pdata->bd->props->brightness = brightness; | ||
308 | down(&pdata->bd->sem); | ||
309 | |||
310 | /* save our data pointer in the interface device */ | ||
311 | usb_set_intfdata(iface, pdata); | ||
312 | |||
313 | printk(KERN_INFO "appledisplay: Apple Cinema Display connected\n"); | ||
314 | |||
315 | return 0; | ||
316 | |||
317 | error: | ||
318 | if (pdata) { | ||
319 | if (pdata->urb) { | ||
320 | usb_kill_urb(pdata->urb); | ||
321 | if (pdata->urbdata) | ||
322 | usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, | ||
323 | pdata->urbdata, pdata->urb->transfer_dma); | ||
324 | usb_free_urb(pdata->urb); | ||
325 | } | ||
326 | if (pdata->bd) | ||
327 | backlight_device_unregister(pdata->bd); | ||
328 | kfree(pdata->msgdata); | ||
329 | } | ||
330 | usb_set_intfdata(iface, NULL); | ||
331 | kfree(pdata); | ||
332 | return retval; | ||
333 | } | ||
334 | |||
335 | static void appledisplay_disconnect(struct usb_interface *iface) | ||
336 | { | ||
337 | struct appledisplay *pdata = usb_get_intfdata(iface); | ||
338 | |||
339 | if (pdata) { | ||
340 | usb_kill_urb(pdata->urb); | ||
341 | cancel_delayed_work(&pdata->work); | ||
342 | backlight_device_unregister(pdata->bd); | ||
343 | usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, | ||
344 | pdata->urbdata, pdata->urb->transfer_dma); | ||
345 | usb_free_urb(pdata->urb); | ||
346 | kfree(pdata->msgdata); | ||
347 | kfree(pdata); | ||
348 | } | ||
349 | |||
350 | printk(KERN_INFO "appledisplay: Apple Cinema Display disconnected\n"); | ||
351 | } | ||
352 | |||
353 | static struct usb_driver appledisplay_driver = { | ||
354 | .name = "appledisplay", | ||
355 | .probe = appledisplay_probe, | ||
356 | .disconnect = appledisplay_disconnect, | ||
357 | .id_table = appledisplay_table, | ||
358 | }; | ||
359 | |||
360 | static int __init appledisplay_init(void) | ||
361 | { | ||
362 | wq = create_singlethread_workqueue("appledisplay"); | ||
363 | if (!wq) { | ||
364 | err("Could not create work queue\n"); | ||
365 | return -ENOMEM; | ||
366 | } | ||
367 | |||
368 | return usb_register(&appledisplay_driver); | ||
369 | } | ||
370 | |||
371 | static void __exit appledisplay_exit(void) | ||
372 | { | ||
373 | flush_workqueue(wq); | ||
374 | destroy_workqueue(wq); | ||
375 | usb_deregister(&appledisplay_driver); | ||
376 | } | ||
377 | |||
378 | MODULE_AUTHOR("Michael Hanselmann"); | ||
379 | MODULE_DESCRIPTION("Apple Cinema Display driver"); | ||
380 | MODULE_LICENSE("GPL"); | ||
381 | |||
382 | module_init(appledisplay_init); | ||
383 | module_exit(appledisplay_exit); | ||
diff --git a/drivers/usb/misc/cy7c63.c b/drivers/usb/misc/cy7c63.c new file mode 100644 index 000000000000..8a1c10b89b76 --- /dev/null +++ b/drivers/usb/misc/cy7c63.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * cy7c63.c | ||
3 | * | ||
4 | * Copyright (c) 2006 Oliver Bock (bock@fh-wolfenbuettel.de) | ||
5 | * | ||
6 | * This driver is based on the Cypress Thermometer USB Driver by | ||
7 | * Marcus Maul and the 2.0 version of Greg Kroah-Hartman's | ||
8 | * USB Skeleton driver. | ||
9 | * | ||
10 | * Is is a generic driver for the Cypress CY7C63000 family. | ||
11 | * For the time being it enables you to toggle the single I/O ports | ||
12 | * of the device. | ||
13 | * | ||
14 | * Supported vendors: AK Modul-Bus Computer GmbH | ||
15 | * Supported devices: CY7C63001A-PC (to be continued...) | ||
16 | * Supported functions: Read/Write Ports (to be continued...) | ||
17 | * | ||
18 | * Chipsets families: CY7C63000, CY7C63001, CY7C63100, CY7C63101 | ||
19 | * | ||
20 | * | ||
21 | * This program is free software; you can redistribute it and/or | ||
22 | * modify it under the terms of the GNU General Public License as | ||
23 | * published by the Free Software Foundation, version 2. | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/usb.h> | ||
30 | |||
31 | #define DRIVER_AUTHOR "Oliver Bock (bock@fh-wolfenbuettel.de)" | ||
32 | #define DRIVER_DESC "Cypress CY7C63xxx USB driver" | ||
33 | |||
34 | #define CY7C63_VENDOR_ID 0xa2c | ||
35 | #define CY7C63_PRODUCT_ID 0x8 | ||
36 | |||
37 | #define CY7C63_READ_PORT 0x4 | ||
38 | #define CY7C63_WRITE_PORT 0x5 | ||
39 | #define CY7C63_READ_RAM 0x2 | ||
40 | #define CY7C63_WRITE_RAM 0x3 | ||
41 | #define CY7C63_READ_ROM 0x1 | ||
42 | |||
43 | #define CY7C63_READ_PORT_ID0 0 | ||
44 | #define CY7C63_WRITE_PORT_ID0 0 | ||
45 | #define CY7C63_READ_PORT_ID1 0x2 | ||
46 | #define CY7C63_WRITE_PORT_ID1 1 | ||
47 | |||
48 | #define CY7C63_MAX_REQSIZE 8 | ||
49 | |||
50 | |||
51 | /* table of devices that work with this driver */ | ||
52 | static struct usb_device_id cy7c63_table [] = { | ||
53 | { USB_DEVICE(CY7C63_VENDOR_ID, CY7C63_PRODUCT_ID) }, | ||
54 | { } | ||
55 | }; | ||
56 | MODULE_DEVICE_TABLE(usb, cy7c63_table); | ||
57 | |||
58 | /* structure to hold all of our device specific stuff */ | ||
59 | struct cy7c63 { | ||
60 | struct usb_device * udev; | ||
61 | char port0; | ||
62 | char port1; | ||
63 | }; | ||
64 | |||
65 | /* used to send usb control messages to device */ | ||
66 | int vendor_command(struct cy7c63 *dev, unsigned char request, | ||
67 | unsigned char address, unsigned char data) { | ||
68 | |||
69 | int retval = 0; | ||
70 | unsigned int pipe; | ||
71 | unsigned char *iobuf; | ||
72 | |||
73 | /* allocate some memory for the i/o buffer*/ | ||
74 | iobuf = kzalloc(CY7C63_MAX_REQSIZE, GFP_KERNEL); | ||
75 | if (!iobuf) { | ||
76 | dev_err(&dev->udev->dev, "Out of memory!\n"); | ||
77 | retval = -ENOMEM; | ||
78 | goto error; | ||
79 | } | ||
80 | |||
81 | dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data); | ||
82 | |||
83 | /* prepare usb control message and send it upstream */ | ||
84 | pipe = usb_rcvctrlpipe(dev->udev, 0); | ||
85 | retval = usb_control_msg(dev->udev, pipe, request, | ||
86 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
87 | address, data, iobuf, CY7C63_MAX_REQSIZE, | ||
88 | USB_CTRL_GET_TIMEOUT); | ||
89 | |||
90 | /* store returned data (more READs to be added!) */ | ||
91 | switch (request) { | ||
92 | case CY7C63_READ_PORT: | ||
93 | if (address == CY7C63_READ_PORT_ID0) { | ||
94 | dev->port0 = iobuf[1]; | ||
95 | dev_dbg(&dev->udev->dev, | ||
96 | "READ_PORT0 returned: %d\n",dev->port0); | ||
97 | } | ||
98 | else if (address == CY7C63_READ_PORT_ID1) { | ||
99 | dev->port1 = iobuf[1]; | ||
100 | dev_dbg(&dev->udev->dev, | ||
101 | "READ_PORT1 returned: %d\n",dev->port1); | ||
102 | } | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | kfree(iobuf); | ||
107 | error: | ||
108 | return retval; | ||
109 | } | ||
110 | |||
111 | #define get_set_port(num,read_id,write_id) \ | ||
112 | static ssize_t set_port##num(struct device *dev, struct device_attribute *attr, \ | ||
113 | const char *buf, size_t count) { \ | ||
114 | \ | ||
115 | int value; \ | ||
116 | int result = 0; \ | ||
117 | \ | ||
118 | struct usb_interface *intf = to_usb_interface(dev); \ | ||
119 | struct cy7c63 *cyp = usb_get_intfdata(intf); \ | ||
120 | \ | ||
121 | dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", num); \ | ||
122 | \ | ||
123 | /* validate input data */ \ | ||
124 | if (sscanf(buf, "%d", &value) < 1) { \ | ||
125 | result = -EINVAL; \ | ||
126 | goto error; \ | ||
127 | } \ | ||
128 | if (value>255 || value<0) { \ | ||
129 | result = -EINVAL; \ | ||
130 | goto error; \ | ||
131 | } \ | ||
132 | \ | ||
133 | result = vendor_command(cyp, CY7C63_WRITE_PORT, write_id, \ | ||
134 | (unsigned char)value); \ | ||
135 | \ | ||
136 | dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n",result); \ | ||
137 | error: \ | ||
138 | return result < 0 ? result : count; \ | ||
139 | } \ | ||
140 | \ | ||
141 | static ssize_t get_port##num(struct device *dev, \ | ||
142 | struct device_attribute *attr, char *buf) { \ | ||
143 | \ | ||
144 | int result = 0; \ | ||
145 | \ | ||
146 | struct usb_interface *intf = to_usb_interface(dev); \ | ||
147 | struct cy7c63 *cyp = usb_get_intfdata(intf); \ | ||
148 | \ | ||
149 | dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", num); \ | ||
150 | \ | ||
151 | result = vendor_command(cyp, CY7C63_READ_PORT, read_id, 0); \ | ||
152 | \ | ||
153 | dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result); \ | ||
154 | \ | ||
155 | return sprintf(buf, "%d", cyp->port##num); \ | ||
156 | } \ | ||
157 | static DEVICE_ATTR(port##num, S_IWUGO | S_IRUGO, get_port##num, set_port##num); | ||
158 | |||
159 | get_set_port(0, CY7C63_READ_PORT_ID0, CY7C63_WRITE_PORT_ID0); | ||
160 | get_set_port(1, CY7C63_READ_PORT_ID1, CY7C63_WRITE_PORT_ID1); | ||
161 | |||
162 | static int cy7c63_probe(struct usb_interface *interface, | ||
163 | const struct usb_device_id *id) { | ||
164 | |||
165 | struct cy7c63 *dev = NULL; | ||
166 | int retval = -ENOMEM; | ||
167 | |||
168 | /* allocate memory for our device state and initialize it */ | ||
169 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
170 | if (dev == NULL) { | ||
171 | dev_err(&dev->udev->dev, "Out of memory!\n"); | ||
172 | goto error; | ||
173 | } | ||
174 | |||
175 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | ||
176 | |||
177 | /* save our data pointer in this interface device */ | ||
178 | usb_set_intfdata(interface, dev); | ||
179 | |||
180 | /* create device attribute files */ | ||
181 | device_create_file(&interface->dev, &dev_attr_port0); | ||
182 | device_create_file(&interface->dev, &dev_attr_port1); | ||
183 | |||
184 | /* let the user know what node this device is now attached to */ | ||
185 | dev_info(&interface->dev, | ||
186 | "Cypress CY7C63xxx device now attached\n"); | ||
187 | |||
188 | retval = 0; | ||
189 | error: | ||
190 | return retval; | ||
191 | } | ||
192 | |||
193 | static void cy7c63_disconnect(struct usb_interface *interface) { | ||
194 | |||
195 | struct cy7c63 *dev; | ||
196 | |||
197 | dev = usb_get_intfdata(interface); | ||
198 | usb_set_intfdata(interface, NULL); | ||
199 | |||
200 | /* remove device attribute files */ | ||
201 | device_remove_file(&interface->dev, &dev_attr_port0); | ||
202 | device_remove_file(&interface->dev, &dev_attr_port1); | ||
203 | |||
204 | usb_put_dev(dev->udev); | ||
205 | |||
206 | dev_info(&interface->dev, | ||
207 | "Cypress CY7C63xxx device now disconnected\n"); | ||
208 | |||
209 | kfree(dev); | ||
210 | } | ||
211 | |||
212 | static struct usb_driver cy7c63_driver = { | ||
213 | .name = "cy7c63", | ||
214 | .probe = cy7c63_probe, | ||
215 | .disconnect = cy7c63_disconnect, | ||
216 | .id_table = cy7c63_table, | ||
217 | }; | ||
218 | |||
219 | static int __init cy7c63_init(void) { | ||
220 | |||
221 | int result; | ||
222 | |||
223 | /* register this driver with the USB subsystem */ | ||
224 | result = usb_register(&cy7c63_driver); | ||
225 | if (result) { | ||
226 | err("Function usb_register failed! Error number: %d\n", result); | ||
227 | } | ||
228 | |||
229 | return result; | ||
230 | } | ||
231 | |||
232 | static void __exit cy7c63_exit(void) { | ||
233 | |||
234 | /* deregister this driver with the USB subsystem */ | ||
235 | usb_deregister(&cy7c63_driver); | ||
236 | } | ||
237 | |||
238 | module_init(cy7c63_init); | ||
239 | module_exit(cy7c63_exit); | ||
240 | |||
241 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
242 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
243 | |||
244 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 997db5d8e35b..13aeea2026cc 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * USB PhidgetInterfaceKit driver 1.0 | 2 | * USB PhidgetInterfaceKit driver 1.0 |
3 | * | 3 | * |
4 | * Copyright (C) 2004 Sean Young <sean@mess.org> | 4 | * Copyright (C) 2004, 2006 Sean Young <sean@mess.org> |
5 | * Copyright (C) 2005 Daniel Saakes <daniel@saakes.net> | ||
5 | * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com> | 6 | * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com> |
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
@@ -25,6 +26,7 @@ | |||
25 | 26 | ||
26 | #define USB_VENDOR_ID_GLAB 0x06c2 | 27 | #define USB_VENDOR_ID_GLAB 0x06c2 |
27 | #define USB_DEVICE_ID_INTERFACEKIT004 0x0040 | 28 | #define USB_DEVICE_ID_INTERFACEKIT004 0x0040 |
29 | #define USB_DEVICE_ID_INTERFACEKIT01616 0x0044 | ||
28 | #define USB_DEVICE_ID_INTERFACEKIT888 0x0045 | 30 | #define USB_DEVICE_ID_INTERFACEKIT888 0x0045 |
29 | #define USB_DEVICE_ID_INTERFACEKIT047 0x0051 | 31 | #define USB_DEVICE_ID_INTERFACEKIT047 0x0051 |
30 | #define USB_DEVICE_ID_INTERFACEKIT088 0x0053 | 32 | #define USB_DEVICE_ID_INTERFACEKIT088 0x0053 |
@@ -32,7 +34,9 @@ | |||
32 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | 34 | #define USB_VENDOR_ID_WISEGROUP 0x0925 |
33 | #define USB_DEVICE_ID_INTERFACEKIT884 0x8201 | 35 | #define USB_DEVICE_ID_INTERFACEKIT884 0x8201 |
34 | 36 | ||
35 | #define MAX_INTERFACES 8 | 37 | #define MAX_INTERFACES 16 |
38 | |||
39 | #define URB_INT_SIZE 8 | ||
36 | 40 | ||
37 | struct driver_interfacekit { | 41 | struct driver_interfacekit { |
38 | int sensors; | 42 | int sensors; |
@@ -52,19 +56,24 @@ ifkit(8, 8, 8, 0); | |||
52 | ifkit(0, 4, 7, 1); | 56 | ifkit(0, 4, 7, 1); |
53 | ifkit(8, 8, 4, 0); | 57 | ifkit(8, 8, 4, 0); |
54 | ifkit(0, 8, 8, 1); | 58 | ifkit(0, 8, 8, 1); |
59 | ifkit(0, 16, 16, 0); | ||
55 | 60 | ||
56 | struct phidget_interfacekit { | 61 | struct interfacekit { |
57 | struct usb_device *udev; | 62 | struct usb_device *udev; |
58 | struct usb_interface *intf; | 63 | struct usb_interface *intf; |
59 | struct driver_interfacekit *ifkit; | 64 | struct driver_interfacekit *ifkit; |
60 | int outputs[MAX_INTERFACES]; | 65 | unsigned long outputs; |
61 | int inputs[MAX_INTERFACES]; | 66 | u8 inputs[MAX_INTERFACES]; |
62 | int sensors[MAX_INTERFACES]; | 67 | u16 sensors[MAX_INTERFACES]; |
63 | u8 lcd_files_on; | 68 | u8 lcd_files_on; |
64 | 69 | ||
65 | struct urb *irq; | 70 | struct urb *irq; |
66 | unsigned char *data; | 71 | unsigned char *data; |
67 | dma_addr_t data_dma; | 72 | dma_addr_t data_dma; |
73 | |||
74 | struct work_struct do_notify; | ||
75 | unsigned long input_events; | ||
76 | unsigned long sensor_events; | ||
68 | }; | 77 | }; |
69 | 78 | ||
70 | static struct usb_device_id id_table[] = { | 79 | static struct usb_device_id id_table[] = { |
@@ -76,33 +85,33 @@ static struct usb_device_id id_table[] = { | |||
76 | .driver_info = (kernel_ulong_t)&ph_047}, | 85 | .driver_info = (kernel_ulong_t)&ph_047}, |
77 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), | 86 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), |
78 | .driver_info = (kernel_ulong_t)&ph_088}, | 87 | .driver_info = (kernel_ulong_t)&ph_088}, |
88 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616), | ||
89 | .driver_info = (kernel_ulong_t)&ph_01616}, | ||
79 | {USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884), | 90 | {USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884), |
80 | .driver_info = (kernel_ulong_t)&ph_884}, | 91 | .driver_info = (kernel_ulong_t)&ph_884}, |
81 | {} | 92 | {} |
82 | }; | 93 | }; |
83 | MODULE_DEVICE_TABLE(usb, id_table); | 94 | MODULE_DEVICE_TABLE(usb, id_table); |
84 | 95 | ||
85 | static int change_outputs(struct phidget_interfacekit *kit, int output_num, int enable) | 96 | static int change_outputs(struct interfacekit *kit, int output_num, int enable) |
86 | { | 97 | { |
87 | unsigned char *buffer; | 98 | u8 *buffer; |
88 | int retval; | 99 | int retval; |
89 | int n; | 100 | |
101 | if (enable) | ||
102 | set_bit(output_num, &kit->outputs); | ||
103 | else | ||
104 | clear_bit(output_num, &kit->outputs); | ||
90 | 105 | ||
91 | buffer = kzalloc(4, GFP_KERNEL); | 106 | buffer = kzalloc(4, GFP_KERNEL); |
92 | if (!buffer) { | 107 | if (!buffer) { |
93 | dev_err(&kit->udev->dev, "%s - out of memory\n", | 108 | dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); |
94 | __FUNCTION__); | ||
95 | return -ENOMEM; | 109 | return -ENOMEM; |
96 | } | 110 | } |
111 | buffer[0] = (u8)kit->outputs; | ||
112 | buffer[1] = (u8)(kit->outputs >> 8); | ||
97 | 113 | ||
98 | kit->outputs[output_num] = enable; | 114 | dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", (u16)kit->outputs); |
99 | for (n=0; n<8; n++) { | ||
100 | if (kit->outputs[n]) { | ||
101 | buffer[0] |= 1 << n; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | dev_dbg(&kit->udev->dev, "sending data: %02x\n", buffer[0]); | ||
106 | 115 | ||
107 | retval = usb_control_msg(kit->udev, | 116 | retval = usb_control_msg(kit->udev, |
108 | usb_sndctrlpipe(kit->udev, 0), | 117 | usb_sndctrlpipe(kit->udev, 0), |
@@ -116,10 +125,10 @@ static int change_outputs(struct phidget_interfacekit *kit, int output_num, int | |||
116 | return retval < 0 ? retval : 0; | 125 | return retval < 0 ? retval : 0; |
117 | } | 126 | } |
118 | 127 | ||
119 | static int change_string(struct phidget_interfacekit *kit, const char *display, unsigned char row) | 128 | static int change_string(struct interfacekit *kit, const char *display, unsigned char row) |
120 | { | 129 | { |
121 | unsigned char *buffer; | 130 | unsigned char *buffer; |
122 | unsigned char *form_buffer; | 131 | unsigned char *form_buffer; |
123 | int retval = -ENOMEM; | 132 | int retval = -ENOMEM; |
124 | int i,j, len, buf_ptr; | 133 | int i,j, len, buf_ptr; |
125 | 134 | ||
@@ -175,7 +184,7 @@ exit: | |||
175 | static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 184 | static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ |
176 | { \ | 185 | { \ |
177 | struct usb_interface *intf = to_usb_interface(dev); \ | 186 | struct usb_interface *intf = to_usb_interface(dev); \ |
178 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ | 187 | struct interfacekit *kit = usb_get_intfdata(intf); \ |
179 | change_string(kit, buf, number - 1); \ | 188 | change_string(kit, buf, number - 1); \ |
180 | return count; \ | 189 | return count; \ |
181 | } \ | 190 | } \ |
@@ -186,7 +195,7 @@ set_lcd_line(2); | |||
186 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 195 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
187 | { | 196 | { |
188 | struct usb_interface *intf = to_usb_interface(dev); | 197 | struct usb_interface *intf = to_usb_interface(dev); |
189 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); | 198 | struct interfacekit *kit = usb_get_intfdata(intf); |
190 | int enabled; | 199 | int enabled; |
191 | unsigned char *buffer; | 200 | unsigned char *buffer; |
192 | int retval = -ENOMEM; | 201 | int retval = -ENOMEM; |
@@ -220,7 +229,7 @@ exit: | |||
220 | } | 229 | } |
221 | static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight); | 230 | static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight); |
222 | 231 | ||
223 | static void remove_lcd_files(struct phidget_interfacekit *kit) | 232 | static void remove_lcd_files(struct interfacekit *kit) |
224 | { | 233 | { |
225 | if (kit->lcd_files_on) { | 234 | if (kit->lcd_files_on) { |
226 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); | 235 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); |
@@ -233,7 +242,7 @@ static void remove_lcd_files(struct phidget_interfacekit *kit) | |||
233 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 242 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
234 | { | 243 | { |
235 | struct usb_interface *intf = to_usb_interface(dev); | 244 | struct usb_interface *intf = to_usb_interface(dev); |
236 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); | 245 | struct interfacekit *kit = usb_get_intfdata(intf); |
237 | int enable; | 246 | int enable; |
238 | 247 | ||
239 | if (kit->ifkit->has_lcd == 0) | 248 | if (kit->ifkit->has_lcd == 0) |
@@ -263,10 +272,10 @@ static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); | |||
263 | 272 | ||
264 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) | 273 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) |
265 | { | 274 | { |
266 | struct phidget_interfacekit *kit = urb->context; | 275 | struct interfacekit *kit = urb->context; |
267 | unsigned char *buffer = kit->data; | 276 | unsigned char *buffer = kit->data; |
277 | int i, level, sensor; | ||
268 | int status; | 278 | int status; |
269 | int n; | ||
270 | 279 | ||
271 | switch (urb->status) { | 280 | switch (urb->status) { |
272 | case 0: /* success */ | 281 | case 0: /* success */ |
@@ -280,22 +289,63 @@ static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) | |||
280 | goto resubmit; | 289 | goto resubmit; |
281 | } | 290 | } |
282 | 291 | ||
283 | for (n=0; n<8; n++) { | 292 | /* digital inputs */ |
284 | kit->inputs[n] = buffer[1] & (1 << n) ? 1 : 0; | 293 | if (kit->ifkit->inputs == 16) { |
294 | for (i=0; i < 8; i++) { | ||
295 | level = (buffer[0] >> i) & 1; | ||
296 | if (kit->inputs[i] != level) { | ||
297 | kit->inputs[i] = level; | ||
298 | set_bit(i, &kit->input_events); | ||
299 | } | ||
300 | level = (buffer[1] >> i) & 1; | ||
301 | if (kit->inputs[8 + i] != level) { | ||
302 | kit->inputs[8 + i] = level; | ||
303 | set_bit(8 + i, &kit->input_events); | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | else if (kit->ifkit->inputs == 8) { | ||
308 | for (i=0; i < 8; i++) { | ||
309 | level = (buffer[1] >> i) & 1; | ||
310 | if (kit->inputs[i] != level) { | ||
311 | kit->inputs[i] = level; | ||
312 | set_bit(i, &kit->input_events); | ||
313 | } | ||
314 | } | ||
285 | } | 315 | } |
286 | 316 | ||
287 | if (buffer[0] & 1) { | 317 | /* analog inputs */ |
288 | kit->sensors[4] = buffer[2] + (buffer[3] & 0x0f) * 256; | 318 | if (kit->ifkit->sensors) { |
289 | kit->sensors[5] = buffer[4] + (buffer[3] & 0xf0) * 16; | 319 | sensor = (buffer[0] & 1) ? 4 : 0; |
290 | kit->sensors[6] = buffer[5] + (buffer[6] & 0x0f) * 256; | 320 | |
291 | kit->sensors[7] = buffer[7] + (buffer[6] & 0xf0) * 16; | 321 | level = buffer[2] + (buffer[3] & 0x0f) * 256; |
292 | } else { | 322 | if (level != kit->sensors[sensor]) { |
293 | kit->sensors[0] = buffer[2] + (buffer[3] & 0x0f) * 256; | 323 | kit->sensors[sensor] = level; |
294 | kit->sensors[1] = buffer[4] + (buffer[3] & 0xf0) * 16; | 324 | set_bit(sensor, &kit->sensor_events); |
295 | kit->sensors[2] = buffer[5] + (buffer[6] & 0x0f) * 256; | 325 | } |
296 | kit->sensors[3] = buffer[7] + (buffer[6] & 0xf0) * 16; | 326 | sensor++; |
327 | level = buffer[4] + (buffer[3] & 0xf0) * 16; | ||
328 | if (level != kit->sensors[sensor]) { | ||
329 | kit->sensors[sensor] = level; | ||
330 | set_bit(sensor, &kit->sensor_events); | ||
331 | } | ||
332 | sensor++; | ||
333 | level = buffer[5] + (buffer[6] & 0x0f) * 256; | ||
334 | if (level != kit->sensors[sensor]) { | ||
335 | kit->sensors[sensor] = level; | ||
336 | set_bit(sensor, &kit->sensor_events); | ||
337 | } | ||
338 | sensor++; | ||
339 | level = buffer[7] + (buffer[6] & 0xf0) * 16; | ||
340 | if (level != kit->sensors[sensor]) { | ||
341 | kit->sensors[sensor] = level; | ||
342 | set_bit(sensor, &kit->sensor_events); | ||
343 | } | ||
297 | } | 344 | } |
298 | 345 | ||
346 | if (kit->input_events || kit->sensor_events) | ||
347 | schedule_work(&kit->do_notify); | ||
348 | |||
299 | resubmit: | 349 | resubmit: |
300 | status = usb_submit_urb(urb, SLAB_ATOMIC); | 350 | status = usb_submit_urb(urb, SLAB_ATOMIC); |
301 | if (status) | 351 | if (status) |
@@ -304,20 +354,40 @@ resubmit: | |||
304 | kit->udev->devpath, status); | 354 | kit->udev->devpath, status); |
305 | } | 355 | } |
306 | 356 | ||
357 | static void do_notify(void *data) | ||
358 | { | ||
359 | struct interfacekit *kit = data; | ||
360 | int i; | ||
361 | char sysfs_file[8]; | ||
362 | |||
363 | for (i=0; i<kit->ifkit->inputs; i++) { | ||
364 | if (test_and_clear_bit(i, &kit->input_events)) { | ||
365 | sprintf(sysfs_file, "input%d", i + 1); | ||
366 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | ||
367 | } | ||
368 | } | ||
369 | |||
370 | for (i=0; i<kit->ifkit->sensors; i++) { | ||
371 | if (test_and_clear_bit(i, &kit->sensor_events)) { | ||
372 | sprintf(sysfs_file, "sensor%d", i + 1); | ||
373 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | |||
307 | #define show_set_output(value) \ | 378 | #define show_set_output(value) \ |
308 | static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ | 379 | static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ |
309 | size_t count) \ | 380 | size_t count) \ |
310 | { \ | 381 | { \ |
311 | struct usb_interface *intf = to_usb_interface(dev); \ | 382 | struct usb_interface *intf = to_usb_interface(dev); \ |
312 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ | 383 | struct interfacekit *kit = usb_get_intfdata(intf); \ |
313 | int enabled; \ | 384 | int enabled; \ |
314 | int retval; \ | 385 | int retval; \ |
315 | \ | 386 | \ |
316 | if (sscanf(buf, "%d", &enabled) < 1) { \ | 387 | if (sscanf(buf, "%d", &enabled) < 1) \ |
317 | return -EINVAL; \ | 388 | return -EINVAL; \ |
318 | } \ | ||
319 | \ | 389 | \ |
320 | retval = change_outputs(kit, value - 1, enabled ? 1 : 0); \ | 390 | retval = change_outputs(kit, value - 1, enabled); \ |
321 | \ | 391 | \ |
322 | return retval ? retval : count; \ | 392 | return retval ? retval : count; \ |
323 | } \ | 393 | } \ |
@@ -325,9 +395,9 @@ static ssize_t set_output##value(struct device *dev, struct device_attribute *at | |||
325 | static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 395 | static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ |
326 | { \ | 396 | { \ |
327 | struct usb_interface *intf = to_usb_interface(dev); \ | 397 | struct usb_interface *intf = to_usb_interface(dev); \ |
328 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ | 398 | struct interfacekit *kit = usb_get_intfdata(intf); \ |
329 | \ | 399 | \ |
330 | return sprintf(buf, "%d\n", kit->outputs[value - 1]); \ | 400 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ |
331 | } \ | 401 | } \ |
332 | static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \ | 402 | static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \ |
333 | show_output##value, set_output##value); | 403 | show_output##value, set_output##value); |
@@ -338,15 +408,23 @@ show_set_output(4); | |||
338 | show_set_output(5); | 408 | show_set_output(5); |
339 | show_set_output(6); | 409 | show_set_output(6); |
340 | show_set_output(7); | 410 | show_set_output(7); |
341 | show_set_output(8); /* should be MAX_INTERFACES - 1 */ | 411 | show_set_output(8); |
412 | show_set_output(9); | ||
413 | show_set_output(10); | ||
414 | show_set_output(11); | ||
415 | show_set_output(12); | ||
416 | show_set_output(13); | ||
417 | show_set_output(14); | ||
418 | show_set_output(15); | ||
419 | show_set_output(16); | ||
342 | 420 | ||
343 | #define show_input(value) \ | 421 | #define show_input(value) \ |
344 | static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 422 | static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ |
345 | { \ | 423 | { \ |
346 | struct usb_interface *intf = to_usb_interface(dev); \ | 424 | struct usb_interface *intf = to_usb_interface(dev); \ |
347 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ | 425 | struct interfacekit *kit = usb_get_intfdata(intf); \ |
348 | \ | 426 | \ |
349 | return sprintf(buf, "%d\n", kit->inputs[value - 1]); \ | 427 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ |
350 | } \ | 428 | } \ |
351 | static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL); | 429 | static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL); |
352 | 430 | ||
@@ -357,15 +435,23 @@ show_input(4); | |||
357 | show_input(5); | 435 | show_input(5); |
358 | show_input(6); | 436 | show_input(6); |
359 | show_input(7); | 437 | show_input(7); |
360 | show_input(8); /* should be MAX_INTERFACES - 1 */ | 438 | show_input(8); |
439 | show_input(9); | ||
440 | show_input(10); | ||
441 | show_input(11); | ||
442 | show_input(12); | ||
443 | show_input(13); | ||
444 | show_input(14); | ||
445 | show_input(15); | ||
446 | show_input(16); | ||
361 | 447 | ||
362 | #define show_sensor(value) \ | 448 | #define show_sensor(value) \ |
363 | static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 449 | static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ |
364 | { \ | 450 | { \ |
365 | struct usb_interface *intf = to_usb_interface(dev); \ | 451 | struct usb_interface *intf = to_usb_interface(dev); \ |
366 | struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ | 452 | struct interfacekit *kit = usb_get_intfdata(intf); \ |
367 | \ | 453 | \ |
368 | return sprintf(buf, "%d\n", kit->sensors[value - 1]); \ | 454 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ |
369 | } \ | 455 | } \ |
370 | static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL); | 456 | static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL); |
371 | 457 | ||
@@ -376,16 +462,16 @@ show_sensor(4); | |||
376 | show_sensor(5); | 462 | show_sensor(5); |
377 | show_sensor(6); | 463 | show_sensor(6); |
378 | show_sensor(7); | 464 | show_sensor(7); |
379 | show_sensor(8); /* should be MAX_INTERFACES - 1 */ | 465 | show_sensor(8); |
380 | 466 | ||
381 | static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) | 467 | static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) |
382 | { | 468 | { |
383 | struct usb_device *dev = interface_to_usbdev(intf); | 469 | struct usb_device *dev = interface_to_usbdev(intf); |
384 | struct usb_host_interface *interface; | 470 | struct usb_host_interface *interface; |
385 | struct usb_endpoint_descriptor *endpoint; | 471 | struct usb_endpoint_descriptor *endpoint; |
386 | struct phidget_interfacekit *kit; | 472 | struct interfacekit *kit; |
387 | struct driver_interfacekit *ifkit; | 473 | struct driver_interfacekit *ifkit; |
388 | int pipe, maxp; | 474 | int pipe, maxp, rc = -ENOMEM; |
389 | 475 | ||
390 | ifkit = (struct driver_interfacekit *)id->driver_info; | 476 | ifkit = (struct driver_interfacekit *)id->driver_info; |
391 | if (!ifkit) | 477 | if (!ifkit) |
@@ -405,29 +491,23 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
405 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | 491 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); |
406 | 492 | ||
407 | kit = kzalloc(sizeof(*kit), GFP_KERNEL); | 493 | kit = kzalloc(sizeof(*kit), GFP_KERNEL); |
408 | if (kit == NULL) { | 494 | if (!kit) |
409 | dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__); | 495 | goto out; |
410 | return -ENOMEM; | ||
411 | } | ||
412 | kit->ifkit = ifkit; | ||
413 | 496 | ||
414 | kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma); | 497 | kit->ifkit = ifkit; |
415 | if (!kit->data) { | 498 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); |
416 | kfree(kit); | 499 | if (!kit->data) |
417 | return -ENOMEM; | 500 | goto out; |
418 | } | ||
419 | 501 | ||
420 | kit->irq = usb_alloc_urb(0, GFP_KERNEL); | 502 | kit->irq = usb_alloc_urb(0, GFP_KERNEL); |
421 | if (!kit->irq) { | 503 | if (!kit->irq) |
422 | usb_buffer_free(dev, 8, kit->data, kit->data_dma); | 504 | goto out; |
423 | kfree(kit); | ||
424 | return -ENOMEM; | ||
425 | } | ||
426 | 505 | ||
427 | kit->udev = usb_get_dev(dev); | 506 | kit->udev = usb_get_dev(dev); |
428 | kit->intf = intf; | 507 | kit->intf = intf; |
508 | INIT_WORK(&kit->do_notify, do_notify, kit); | ||
429 | usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, | 509 | usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, |
430 | (maxp > 8 ? 8 : maxp), | 510 | maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, |
431 | interfacekit_irq, kit, endpoint->bInterval); | 511 | interfacekit_irq, kit, endpoint->bInterval); |
432 | kit->irq->transfer_dma = kit->data_dma; | 512 | kit->irq->transfer_dma = kit->data_dma; |
433 | kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 513 | kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
@@ -435,7 +515,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
435 | usb_set_intfdata(intf, kit); | 515 | usb_set_intfdata(intf, kit); |
436 | 516 | ||
437 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { | 517 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { |
438 | return -EIO; | 518 | rc = -EIO; |
519 | goto out; | ||
439 | } | 520 | } |
440 | 521 | ||
441 | if (ifkit->outputs >= 4) { | 522 | if (ifkit->outputs >= 4) { |
@@ -444,12 +525,22 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
444 | device_create_file(&intf->dev, &dev_attr_output3); | 525 | device_create_file(&intf->dev, &dev_attr_output3); |
445 | device_create_file(&intf->dev, &dev_attr_output4); | 526 | device_create_file(&intf->dev, &dev_attr_output4); |
446 | } | 527 | } |
447 | if (ifkit->outputs == 8) { | 528 | if (ifkit->outputs >= 8) { |
448 | device_create_file(&intf->dev, &dev_attr_output5); | 529 | device_create_file(&intf->dev, &dev_attr_output5); |
449 | device_create_file(&intf->dev, &dev_attr_output6); | 530 | device_create_file(&intf->dev, &dev_attr_output6); |
450 | device_create_file(&intf->dev, &dev_attr_output7); | 531 | device_create_file(&intf->dev, &dev_attr_output7); |
451 | device_create_file(&intf->dev, &dev_attr_output8); | 532 | device_create_file(&intf->dev, &dev_attr_output8); |
452 | } | 533 | } |
534 | if (ifkit->outputs == 16) { | ||
535 | device_create_file(&intf->dev, &dev_attr_output9); | ||
536 | device_create_file(&intf->dev, &dev_attr_output10); | ||
537 | device_create_file(&intf->dev, &dev_attr_output11); | ||
538 | device_create_file(&intf->dev, &dev_attr_output12); | ||
539 | device_create_file(&intf->dev, &dev_attr_output13); | ||
540 | device_create_file(&intf->dev, &dev_attr_output14); | ||
541 | device_create_file(&intf->dev, &dev_attr_output15); | ||
542 | device_create_file(&intf->dev, &dev_attr_output16); | ||
543 | } | ||
453 | 544 | ||
454 | if (ifkit->inputs >= 4) { | 545 | if (ifkit->inputs >= 4) { |
455 | device_create_file(&intf->dev, &dev_attr_input1); | 546 | device_create_file(&intf->dev, &dev_attr_input1); |
@@ -457,12 +548,22 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
457 | device_create_file(&intf->dev, &dev_attr_input3); | 548 | device_create_file(&intf->dev, &dev_attr_input3); |
458 | device_create_file(&intf->dev, &dev_attr_input4); | 549 | device_create_file(&intf->dev, &dev_attr_input4); |
459 | } | 550 | } |
460 | if (ifkit->inputs == 8) { | 551 | if (ifkit->inputs >= 8) { |
461 | device_create_file(&intf->dev, &dev_attr_input5); | 552 | device_create_file(&intf->dev, &dev_attr_input5); |
462 | device_create_file(&intf->dev, &dev_attr_input6); | 553 | device_create_file(&intf->dev, &dev_attr_input6); |
463 | device_create_file(&intf->dev, &dev_attr_input7); | 554 | device_create_file(&intf->dev, &dev_attr_input7); |
464 | device_create_file(&intf->dev, &dev_attr_input8); | 555 | device_create_file(&intf->dev, &dev_attr_input8); |
465 | } | 556 | } |
557 | if (ifkit->inputs == 16) { | ||
558 | device_create_file(&intf->dev, &dev_attr_input9); | ||
559 | device_create_file(&intf->dev, &dev_attr_input10); | ||
560 | device_create_file(&intf->dev, &dev_attr_input11); | ||
561 | device_create_file(&intf->dev, &dev_attr_input12); | ||
562 | device_create_file(&intf->dev, &dev_attr_input13); | ||
563 | device_create_file(&intf->dev, &dev_attr_input14); | ||
564 | device_create_file(&intf->dev, &dev_attr_input15); | ||
565 | device_create_file(&intf->dev, &dev_attr_input16); | ||
566 | } | ||
466 | 567 | ||
467 | if (ifkit->sensors >= 4) { | 568 | if (ifkit->sensors >= 4) { |
468 | device_create_file(&intf->dev, &dev_attr_sensor1); | 569 | device_create_file(&intf->dev, &dev_attr_sensor1); |
@@ -475,9 +576,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
475 | device_create_file(&intf->dev, &dev_attr_sensor6); | 576 | device_create_file(&intf->dev, &dev_attr_sensor6); |
476 | device_create_file(&intf->dev, &dev_attr_sensor7); | 577 | device_create_file(&intf->dev, &dev_attr_sensor7); |
477 | } | 578 | } |
478 | if (ifkit->sensors == 8) { | 579 | if (ifkit->sensors == 8) |
479 | device_create_file(&intf->dev, &dev_attr_sensor8); | 580 | device_create_file(&intf->dev, &dev_attr_sensor8); |
480 | } | ||
481 | 581 | ||
482 | if (ifkit->has_lcd) | 582 | if (ifkit->has_lcd) |
483 | device_create_file(&intf->dev, &dev_attr_lcd); | 583 | device_create_file(&intf->dev, &dev_attr_lcd); |
@@ -486,29 +586,56 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
486 | ifkit->sensors, ifkit->inputs, ifkit->outputs); | 586 | ifkit->sensors, ifkit->inputs, ifkit->outputs); |
487 | 587 | ||
488 | return 0; | 588 | return 0; |
589 | |||
590 | out: | ||
591 | if (kit) { | ||
592 | if (kit->irq) | ||
593 | usb_free_urb(kit->irq); | ||
594 | if (kit->data) | ||
595 | usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); | ||
596 | kfree(kit); | ||
597 | } | ||
598 | |||
599 | return rc; | ||
489 | } | 600 | } |
490 | 601 | ||
491 | static void interfacekit_disconnect(struct usb_interface *interface) | 602 | static void interfacekit_disconnect(struct usb_interface *interface) |
492 | { | 603 | { |
493 | struct phidget_interfacekit *kit; | 604 | struct interfacekit *kit; |
494 | 605 | ||
495 | kit = usb_get_intfdata(interface); | 606 | kit = usb_get_intfdata(interface); |
496 | usb_set_intfdata(interface, NULL); | 607 | usb_set_intfdata(interface, NULL); |
497 | if (!kit) | 608 | if (!kit) |
498 | return; | 609 | return; |
499 | 610 | ||
611 | usb_kill_urb(kit->irq); | ||
612 | usb_free_urb(kit->irq); | ||
613 | usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); | ||
614 | |||
615 | cancel_delayed_work(&kit->do_notify); | ||
616 | |||
500 | if (kit->ifkit->outputs >= 4) { | 617 | if (kit->ifkit->outputs >= 4) { |
501 | device_remove_file(&interface->dev, &dev_attr_output1); | 618 | device_remove_file(&interface->dev, &dev_attr_output1); |
502 | device_remove_file(&interface->dev, &dev_attr_output2); | 619 | device_remove_file(&interface->dev, &dev_attr_output2); |
503 | device_remove_file(&interface->dev, &dev_attr_output3); | 620 | device_remove_file(&interface->dev, &dev_attr_output3); |
504 | device_remove_file(&interface->dev, &dev_attr_output4); | 621 | device_remove_file(&interface->dev, &dev_attr_output4); |
505 | } | 622 | } |
506 | if (kit->ifkit->outputs == 8) { | 623 | if (kit->ifkit->outputs >= 8) { |
507 | device_remove_file(&interface->dev, &dev_attr_output5); | 624 | device_remove_file(&interface->dev, &dev_attr_output5); |
508 | device_remove_file(&interface->dev, &dev_attr_output6); | 625 | device_remove_file(&interface->dev, &dev_attr_output6); |
509 | device_remove_file(&interface->dev, &dev_attr_output7); | 626 | device_remove_file(&interface->dev, &dev_attr_output7); |
510 | device_remove_file(&interface->dev, &dev_attr_output8); | 627 | device_remove_file(&interface->dev, &dev_attr_output8); |
511 | } | 628 | } |
629 | if (kit->ifkit->outputs == 16) { | ||
630 | device_remove_file(&interface->dev, &dev_attr_output9); | ||
631 | device_remove_file(&interface->dev, &dev_attr_output10); | ||
632 | device_remove_file(&interface->dev, &dev_attr_output11); | ||
633 | device_remove_file(&interface->dev, &dev_attr_output12); | ||
634 | device_remove_file(&interface->dev, &dev_attr_output13); | ||
635 | device_remove_file(&interface->dev, &dev_attr_output14); | ||
636 | device_remove_file(&interface->dev, &dev_attr_output15); | ||
637 | device_remove_file(&interface->dev, &dev_attr_output16); | ||
638 | } | ||
512 | 639 | ||
513 | if (kit->ifkit->inputs >= 4) { | 640 | if (kit->ifkit->inputs >= 4) { |
514 | device_remove_file(&interface->dev, &dev_attr_input1); | 641 | device_remove_file(&interface->dev, &dev_attr_input1); |
@@ -516,12 +643,22 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
516 | device_remove_file(&interface->dev, &dev_attr_input3); | 643 | device_remove_file(&interface->dev, &dev_attr_input3); |
517 | device_remove_file(&interface->dev, &dev_attr_input4); | 644 | device_remove_file(&interface->dev, &dev_attr_input4); |
518 | } | 645 | } |
519 | if (kit->ifkit->inputs == 8) { | 646 | if (kit->ifkit->inputs >= 8) { |
520 | device_remove_file(&interface->dev, &dev_attr_input5); | 647 | device_remove_file(&interface->dev, &dev_attr_input5); |
521 | device_remove_file(&interface->dev, &dev_attr_input6); | 648 | device_remove_file(&interface->dev, &dev_attr_input6); |
522 | device_remove_file(&interface->dev, &dev_attr_input7); | 649 | device_remove_file(&interface->dev, &dev_attr_input7); |
523 | device_remove_file(&interface->dev, &dev_attr_input8); | 650 | device_remove_file(&interface->dev, &dev_attr_input8); |
524 | } | 651 | } |
652 | if (kit->ifkit->inputs == 16) { | ||
653 | device_remove_file(&interface->dev, &dev_attr_input9); | ||
654 | device_remove_file(&interface->dev, &dev_attr_input10); | ||
655 | device_remove_file(&interface->dev, &dev_attr_input11); | ||
656 | device_remove_file(&interface->dev, &dev_attr_input12); | ||
657 | device_remove_file(&interface->dev, &dev_attr_input13); | ||
658 | device_remove_file(&interface->dev, &dev_attr_input14); | ||
659 | device_remove_file(&interface->dev, &dev_attr_input15); | ||
660 | device_remove_file(&interface->dev, &dev_attr_input16); | ||
661 | } | ||
525 | 662 | ||
526 | if (kit->ifkit->sensors >= 4) { | 663 | if (kit->ifkit->sensors >= 4) { |
527 | device_remove_file(&interface->dev, &dev_attr_sensor1); | 664 | device_remove_file(&interface->dev, &dev_attr_sensor1); |
@@ -534,19 +671,15 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
534 | device_remove_file(&interface->dev, &dev_attr_sensor6); | 671 | device_remove_file(&interface->dev, &dev_attr_sensor6); |
535 | device_remove_file(&interface->dev, &dev_attr_sensor7); | 672 | device_remove_file(&interface->dev, &dev_attr_sensor7); |
536 | } | 673 | } |
537 | if (kit->ifkit->sensors == 8) { | 674 | if (kit->ifkit->sensors == 8) |
538 | device_remove_file(&interface->dev, &dev_attr_sensor8); | 675 | device_remove_file(&interface->dev, &dev_attr_sensor8); |
539 | } | 676 | |
540 | if (kit->ifkit->has_lcd) | 677 | if (kit->ifkit->has_lcd) |
541 | device_remove_file(&interface->dev, &dev_attr_lcd); | 678 | device_remove_file(&interface->dev, &dev_attr_lcd); |
542 | 679 | ||
543 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", | 680 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", |
544 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); | 681 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); |
545 | 682 | ||
546 | usb_kill_urb(kit->irq); | ||
547 | usb_free_urb(kit->irq); | ||
548 | usb_buffer_free(kit->udev, 8, kit->data, kit->data_dma); | ||
549 | |||
550 | usb_put_dev(kit->udev); | 683 | usb_put_dev(kit->udev); |
551 | kfree(kit); | 684 | kfree(kit); |
552 | } | 685 | } |
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 196c8794a73c..738bd7c7451f 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c | |||
@@ -37,6 +37,7 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include <linux/config.h> | 39 | #include <linux/config.h> |
40 | #include <linux/mutex.h> | ||
40 | #include <linux/module.h> | 41 | #include <linux/module.h> |
41 | #include <linux/kernel.h> | 42 | #include <linux/kernel.h> |
42 | #include <linux/signal.h> | 43 | #include <linux/signal.h> |
@@ -52,6 +53,7 @@ | |||
52 | #include <linux/vmalloc.h> | 53 | #include <linux/vmalloc.h> |
53 | 54 | ||
54 | #include "sisusb.h" | 55 | #include "sisusb.h" |
56 | #include "sisusb_init.h" | ||
55 | 57 | ||
56 | #ifdef INCL_SISUSB_CON | 58 | #ifdef INCL_SISUSB_CON |
57 | #include <linux/font.h> | 59 | #include <linux/font.h> |
@@ -62,36 +64,6 @@ | |||
62 | /* Forward declarations / clean-up routines */ | 64 | /* Forward declarations / clean-up routines */ |
63 | 65 | ||
64 | #ifdef INCL_SISUSB_CON | 66 | #ifdef INCL_SISUSB_CON |
65 | int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data); | ||
66 | int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data); | ||
67 | int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data); | ||
68 | int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data); | ||
69 | int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor); | ||
70 | int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor); | ||
71 | int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand); | ||
72 | |||
73 | int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); | ||
74 | int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); | ||
75 | int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data); | ||
76 | int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data); | ||
77 | int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, | ||
78 | u32 dest, int length, size_t *bytes_written); | ||
79 | |||
80 | int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); | ||
81 | |||
82 | extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); | ||
83 | extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); | ||
84 | |||
85 | extern void sisusb_init_concode(void); | ||
86 | extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last); | ||
87 | extern void sisusb_console_exit(struct sisusb_usb_data *sisusb); | ||
88 | |||
89 | extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location); | ||
90 | |||
91 | extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, | ||
92 | u8 *arg, int cmapsz, int ch512, int dorecalc, | ||
93 | struct vc_data *c, int fh, int uplock); | ||
94 | |||
95 | static int sisusb_first_vc = 0; | 67 | static int sisusb_first_vc = 0; |
96 | static int sisusb_last_vc = 0; | 68 | static int sisusb_last_vc = 0; |
97 | module_param_named(first, sisusb_first_vc, int, 0); | 69 | module_param_named(first, sisusb_first_vc, int, 0); |
@@ -102,7 +74,7 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES | |||
102 | 74 | ||
103 | static struct usb_driver sisusb_driver; | 75 | static struct usb_driver sisusb_driver; |
104 | 76 | ||
105 | DECLARE_MUTEX(disconnect_sem); | 77 | DEFINE_MUTEX(disconnect_mutex); |
106 | 78 | ||
107 | static void | 79 | static void |
108 | sisusb_free_buffers(struct sisusb_usb_data *sisusb) | 80 | sisusb_free_buffers(struct sisusb_usb_data *sisusb) |
@@ -1359,9 +1331,6 @@ sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data) | |||
1359 | } | 1331 | } |
1360 | #endif | 1332 | #endif |
1361 | 1333 | ||
1362 | #ifndef INCL_SISUSB_CON | ||
1363 | static | ||
1364 | #endif | ||
1365 | int | 1334 | int |
1366 | sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) | 1335 | sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) |
1367 | { | 1336 | { |
@@ -1371,9 +1340,6 @@ sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) | |||
1371 | return ret; | 1340 | return ret; |
1372 | } | 1341 | } |
1373 | 1342 | ||
1374 | #ifndef INCL_SISUSB_CON | ||
1375 | static | ||
1376 | #endif | ||
1377 | int | 1343 | int |
1378 | sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) | 1344 | sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) |
1379 | { | 1345 | { |
@@ -1383,9 +1349,6 @@ sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) | |||
1383 | return ret; | 1349 | return ret; |
1384 | } | 1350 | } |
1385 | 1351 | ||
1386 | #ifndef INCL_SISUSB_CON | ||
1387 | static | ||
1388 | #endif | ||
1389 | int | 1352 | int |
1390 | sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, | 1353 | sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, |
1391 | u8 myand, u8 myor) | 1354 | u8 myand, u8 myor) |
@@ -1415,18 +1378,12 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx, | |||
1415 | return ret; | 1378 | return ret; |
1416 | } | 1379 | } |
1417 | 1380 | ||
1418 | #ifndef INCL_SISUSB_CON | ||
1419 | static | ||
1420 | #endif | ||
1421 | int | 1381 | int |
1422 | sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) | 1382 | sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) |
1423 | { | 1383 | { |
1424 | return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); | 1384 | return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); |
1425 | } | 1385 | } |
1426 | 1386 | ||
1427 | #ifndef INCL_SISUSB_CON | ||
1428 | static | ||
1429 | #endif | ||
1430 | int | 1387 | int |
1431 | sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) | 1388 | sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) |
1432 | { | 1389 | { |
@@ -1448,6 +1405,8 @@ sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data) | |||
1448 | return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); | 1405 | return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); |
1449 | } | 1406 | } |
1450 | 1407 | ||
1408 | #if 0 | ||
1409 | |||
1451 | int | 1410 | int |
1452 | sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data) | 1411 | sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data) |
1453 | { | 1412 | { |
@@ -1460,6 +1419,8 @@ sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data) | |||
1460 | return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data)); | 1419 | return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data)); |
1461 | } | 1420 | } |
1462 | 1421 | ||
1422 | #endif /* 0 */ | ||
1423 | |||
1463 | int | 1424 | int |
1464 | sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, | 1425 | sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, |
1465 | u32 dest, int length, size_t *bytes_written) | 1426 | u32 dest, int length, size_t *bytes_written) |
@@ -2552,39 +2513,39 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2552 | struct usb_interface *interface; | 2513 | struct usb_interface *interface; |
2553 | int subminor = iminor(inode); | 2514 | int subminor = iminor(inode); |
2554 | 2515 | ||
2555 | down(&disconnect_sem); | 2516 | mutex_lock(&disconnect_mutex); |
2556 | 2517 | ||
2557 | if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { | 2518 | if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { |
2558 | printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", | 2519 | printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", |
2559 | subminor); | 2520 | subminor); |
2560 | up(&disconnect_sem); | 2521 | mutex_unlock(&disconnect_mutex); |
2561 | return -ENODEV; | 2522 | return -ENODEV; |
2562 | } | 2523 | } |
2563 | 2524 | ||
2564 | if (!(sisusb = usb_get_intfdata(interface))) { | 2525 | if (!(sisusb = usb_get_intfdata(interface))) { |
2565 | up(&disconnect_sem); | 2526 | mutex_unlock(&disconnect_mutex); |
2566 | return -ENODEV; | 2527 | return -ENODEV; |
2567 | } | 2528 | } |
2568 | 2529 | ||
2569 | down(&sisusb->lock); | 2530 | mutex_lock(&sisusb->lock); |
2570 | 2531 | ||
2571 | if (!sisusb->present || !sisusb->ready) { | 2532 | if (!sisusb->present || !sisusb->ready) { |
2572 | up(&sisusb->lock); | 2533 | mutex_unlock(&sisusb->lock); |
2573 | up(&disconnect_sem); | 2534 | mutex_unlock(&disconnect_mutex); |
2574 | return -ENODEV; | 2535 | return -ENODEV; |
2575 | } | 2536 | } |
2576 | 2537 | ||
2577 | if (sisusb->isopen) { | 2538 | if (sisusb->isopen) { |
2578 | up(&sisusb->lock); | 2539 | mutex_unlock(&sisusb->lock); |
2579 | up(&disconnect_sem); | 2540 | mutex_unlock(&disconnect_mutex); |
2580 | return -EBUSY; | 2541 | return -EBUSY; |
2581 | } | 2542 | } |
2582 | 2543 | ||
2583 | if (!sisusb->devinit) { | 2544 | if (!sisusb->devinit) { |
2584 | if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { | 2545 | if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { |
2585 | if (sisusb_init_gfxdevice(sisusb, 0)) { | 2546 | if (sisusb_init_gfxdevice(sisusb, 0)) { |
2586 | up(&sisusb->lock); | 2547 | mutex_unlock(&sisusb->lock); |
2587 | up(&disconnect_sem); | 2548 | mutex_unlock(&disconnect_mutex); |
2588 | printk(KERN_ERR | 2549 | printk(KERN_ERR |
2589 | "sisusbvga[%d]: Failed to initialize " | 2550 | "sisusbvga[%d]: Failed to initialize " |
2590 | "device\n", | 2551 | "device\n", |
@@ -2592,8 +2553,8 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2592 | return -EIO; | 2553 | return -EIO; |
2593 | } | 2554 | } |
2594 | } else { | 2555 | } else { |
2595 | up(&sisusb->lock); | 2556 | mutex_unlock(&sisusb->lock); |
2596 | up(&disconnect_sem); | 2557 | mutex_unlock(&disconnect_mutex); |
2597 | printk(KERN_ERR | 2558 | printk(KERN_ERR |
2598 | "sisusbvga[%d]: Device not attached to " | 2559 | "sisusbvga[%d]: Device not attached to " |
2599 | "USB 2.0 hub\n", | 2560 | "USB 2.0 hub\n", |
@@ -2609,9 +2570,9 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2609 | 2570 | ||
2610 | file->private_data = sisusb; | 2571 | file->private_data = sisusb; |
2611 | 2572 | ||
2612 | up(&sisusb->lock); | 2573 | mutex_unlock(&sisusb->lock); |
2613 | 2574 | ||
2614 | up(&disconnect_sem); | 2575 | mutex_unlock(&disconnect_mutex); |
2615 | 2576 | ||
2616 | return 0; | 2577 | return 0; |
2617 | } | 2578 | } |
@@ -2642,14 +2603,14 @@ sisusb_release(struct inode *inode, struct file *file) | |||
2642 | struct sisusb_usb_data *sisusb; | 2603 | struct sisusb_usb_data *sisusb; |
2643 | int myminor; | 2604 | int myminor; |
2644 | 2605 | ||
2645 | down(&disconnect_sem); | 2606 | mutex_lock(&disconnect_mutex); |
2646 | 2607 | ||
2647 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) { | 2608 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) { |
2648 | up(&disconnect_sem); | 2609 | mutex_unlock(&disconnect_mutex); |
2649 | return -ENODEV; | 2610 | return -ENODEV; |
2650 | } | 2611 | } |
2651 | 2612 | ||
2652 | down(&sisusb->lock); | 2613 | mutex_lock(&sisusb->lock); |
2653 | 2614 | ||
2654 | if (sisusb->present) { | 2615 | if (sisusb->present) { |
2655 | /* Wait for all URBs to finish if device still present */ | 2616 | /* Wait for all URBs to finish if device still present */ |
@@ -2662,12 +2623,12 @@ sisusb_release(struct inode *inode, struct file *file) | |||
2662 | sisusb->isopen = 0; | 2623 | sisusb->isopen = 0; |
2663 | file->private_data = NULL; | 2624 | file->private_data = NULL; |
2664 | 2625 | ||
2665 | up(&sisusb->lock); | 2626 | mutex_unlock(&sisusb->lock); |
2666 | 2627 | ||
2667 | /* decrement the usage count on our device */ | 2628 | /* decrement the usage count on our device */ |
2668 | kref_put(&sisusb->kref, sisusb_delete); | 2629 | kref_put(&sisusb->kref, sisusb_delete); |
2669 | 2630 | ||
2670 | up(&disconnect_sem); | 2631 | mutex_unlock(&disconnect_mutex); |
2671 | 2632 | ||
2672 | return 0; | 2633 | return 0; |
2673 | } | 2634 | } |
@@ -2685,11 +2646,11 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | |||
2685 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 2646 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) |
2686 | return -ENODEV; | 2647 | return -ENODEV; |
2687 | 2648 | ||
2688 | down(&sisusb->lock); | 2649 | mutex_lock(&sisusb->lock); |
2689 | 2650 | ||
2690 | /* Sanity check */ | 2651 | /* Sanity check */ |
2691 | if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { | 2652 | if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { |
2692 | up(&sisusb->lock); | 2653 | mutex_unlock(&sisusb->lock); |
2693 | return -ENODEV; | 2654 | return -ENODEV; |
2694 | } | 2655 | } |
2695 | 2656 | ||
@@ -2784,7 +2745,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | |||
2784 | (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { | 2745 | (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { |
2785 | 2746 | ||
2786 | if (count != 4) { | 2747 | if (count != 4) { |
2787 | up(&sisusb->lock); | 2748 | mutex_unlock(&sisusb->lock); |
2788 | return -EINVAL; | 2749 | return -EINVAL; |
2789 | } | 2750 | } |
2790 | 2751 | ||
@@ -2808,7 +2769,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | |||
2808 | 2769 | ||
2809 | (*ppos) += bytes_read; | 2770 | (*ppos) += bytes_read; |
2810 | 2771 | ||
2811 | up(&sisusb->lock); | 2772 | mutex_unlock(&sisusb->lock); |
2812 | 2773 | ||
2813 | return errno ? errno : bytes_read; | 2774 | return errno ? errno : bytes_read; |
2814 | } | 2775 | } |
@@ -2827,11 +2788,11 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, | |||
2827 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 2788 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) |
2828 | return -ENODEV; | 2789 | return -ENODEV; |
2829 | 2790 | ||
2830 | down(&sisusb->lock); | 2791 | mutex_lock(&sisusb->lock); |
2831 | 2792 | ||
2832 | /* Sanity check */ | 2793 | /* Sanity check */ |
2833 | if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { | 2794 | if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { |
2834 | up(&sisusb->lock); | 2795 | mutex_unlock(&sisusb->lock); |
2835 | return -ENODEV; | 2796 | return -ENODEV; |
2836 | } | 2797 | } |
2837 | 2798 | ||
@@ -2930,7 +2891,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, | |||
2930 | (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) { | 2891 | (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) { |
2931 | 2892 | ||
2932 | if (count != 4) { | 2893 | if (count != 4) { |
2933 | up(&sisusb->lock); | 2894 | mutex_unlock(&sisusb->lock); |
2934 | return -EINVAL; | 2895 | return -EINVAL; |
2935 | } | 2896 | } |
2936 | 2897 | ||
@@ -2956,7 +2917,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, | |||
2956 | 2917 | ||
2957 | (*ppos) += bytes_written; | 2918 | (*ppos) += bytes_written; |
2958 | 2919 | ||
2959 | up(&sisusb->lock); | 2920 | mutex_unlock(&sisusb->lock); |
2960 | 2921 | ||
2961 | return errno ? errno : bytes_written; | 2922 | return errno ? errno : bytes_written; |
2962 | } | 2923 | } |
@@ -2970,11 +2931,11 @@ sisusb_lseek(struct file *file, loff_t offset, int orig) | |||
2970 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 2931 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) |
2971 | return -ENODEV; | 2932 | return -ENODEV; |
2972 | 2933 | ||
2973 | down(&sisusb->lock); | 2934 | mutex_lock(&sisusb->lock); |
2974 | 2935 | ||
2975 | /* Sanity check */ | 2936 | /* Sanity check */ |
2976 | if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { | 2937 | if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { |
2977 | up(&sisusb->lock); | 2938 | mutex_unlock(&sisusb->lock); |
2978 | return -ENODEV; | 2939 | return -ENODEV; |
2979 | } | 2940 | } |
2980 | 2941 | ||
@@ -2994,7 +2955,7 @@ sisusb_lseek(struct file *file, loff_t offset, int orig) | |||
2994 | ret = -EINVAL; | 2955 | ret = -EINVAL; |
2995 | } | 2956 | } |
2996 | 2957 | ||
2997 | up(&sisusb->lock); | 2958 | mutex_unlock(&sisusb->lock); |
2998 | return ret; | 2959 | return ret; |
2999 | } | 2960 | } |
3000 | 2961 | ||
@@ -3136,7 +3097,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
3136 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 3097 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) |
3137 | return -ENODEV; | 3098 | return -ENODEV; |
3138 | 3099 | ||
3139 | down(&sisusb->lock); | 3100 | mutex_lock(&sisusb->lock); |
3140 | 3101 | ||
3141 | /* Sanity check */ | 3102 | /* Sanity check */ |
3142 | if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { | 3103 | if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { |
@@ -3193,7 +3154,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
3193 | } | 3154 | } |
3194 | 3155 | ||
3195 | err_out: | 3156 | err_out: |
3196 | up(&sisusb->lock); | 3157 | mutex_unlock(&sisusb->lock); |
3197 | return retval; | 3158 | return retval; |
3198 | } | 3159 | } |
3199 | 3160 | ||
@@ -3258,7 +3219,7 @@ static int sisusb_probe(struct usb_interface *intf, | |||
3258 | } | 3219 | } |
3259 | kref_init(&sisusb->kref); | 3220 | kref_init(&sisusb->kref); |
3260 | 3221 | ||
3261 | init_MUTEX(&(sisusb->lock)); | 3222 | mutex_init(&(sisusb->lock)); |
3262 | 3223 | ||
3263 | /* Register device */ | 3224 | /* Register device */ |
3264 | if ((retval = usb_register_dev(intf, &usb_sisusb_class))) { | 3225 | if ((retval = usb_register_dev(intf, &usb_sisusb_class))) { |
@@ -3429,9 +3390,9 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3429 | * protect all other routines from the disconnect | 3390 | * protect all other routines from the disconnect |
3430 | * case, not the other way round. | 3391 | * case, not the other way round. |
3431 | */ | 3392 | */ |
3432 | down(&disconnect_sem); | 3393 | mutex_lock(&disconnect_mutex); |
3433 | 3394 | ||
3434 | down(&sisusb->lock); | 3395 | mutex_lock(&sisusb->lock); |
3435 | 3396 | ||
3436 | /* Wait for all URBs to complete and kill them in case (MUST do) */ | 3397 | /* Wait for all URBs to complete and kill them in case (MUST do) */ |
3437 | if (!sisusb_wait_all_out_complete(sisusb)) | 3398 | if (!sisusb_wait_all_out_complete(sisusb)) |
@@ -3462,12 +3423,12 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3462 | sisusb->present = 0; | 3423 | sisusb->present = 0; |
3463 | sisusb->ready = 0; | 3424 | sisusb->ready = 0; |
3464 | 3425 | ||
3465 | up(&sisusb->lock); | 3426 | mutex_unlock(&sisusb->lock); |
3466 | 3427 | ||
3467 | /* decrement our usage count */ | 3428 | /* decrement our usage count */ |
3468 | kref_put(&sisusb->kref, sisusb_delete); | 3429 | kref_put(&sisusb->kref, sisusb_delete); |
3469 | 3430 | ||
3470 | up(&disconnect_sem); | 3431 | mutex_unlock(&disconnect_mutex); |
3471 | 3432 | ||
3472 | printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); | 3433 | printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); |
3473 | } | 3434 | } |
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h index a716825d1f9b..8e1120a64806 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.h +++ b/drivers/usb/misc/sisusbvga/sisusb.h | |||
@@ -41,6 +41,8 @@ | |||
41 | #define SISUSB_NEW_CONFIG_COMPAT | 41 | #define SISUSB_NEW_CONFIG_COMPAT |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | #include <linux/mutex.h> | ||
45 | |||
44 | /* For older kernels, support for text consoles is by default | 46 | /* For older kernels, support for text consoles is by default |
45 | * off. To ensable text console support, change the following: | 47 | * off. To ensable text console support, change the following: |
46 | */ | 48 | */ |
@@ -60,11 +62,9 @@ | |||
60 | #define INCL_SISUSB_CON 1 | 62 | #define INCL_SISUSB_CON 1 |
61 | #endif | 63 | #endif |
62 | 64 | ||
63 | #ifdef INCL_SISUSB_CON | ||
64 | #include <linux/console.h> | 65 | #include <linux/console.h> |
65 | #include <linux/vt_kern.h> | 66 | #include <linux/vt_kern.h> |
66 | #include "sisusb_struct.h" | 67 | #include "sisusb_struct.h" |
67 | #endif | ||
68 | 68 | ||
69 | /* USB related */ | 69 | /* USB related */ |
70 | 70 | ||
@@ -116,7 +116,7 @@ struct sisusb_usb_data { | |||
116 | struct usb_interface *interface; | 116 | struct usb_interface *interface; |
117 | struct kref kref; | 117 | struct kref kref; |
118 | wait_queue_head_t wait_q; /* for syncind and timeouts */ | 118 | wait_queue_head_t wait_q; /* for syncind and timeouts */ |
119 | struct semaphore lock; /* general race avoidance */ | 119 | struct mutex lock; /* general race avoidance */ |
120 | unsigned int ifnum; /* interface number of the USB device */ | 120 | unsigned int ifnum; /* interface number of the USB device */ |
121 | int minor; /* minor (for logging clarity) */ | 121 | int minor; /* minor (for logging clarity) */ |
122 | int isopen; /* !=0 if open */ | 122 | int isopen; /* !=0 if open */ |
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index be5c1a25ae21..fb48feca8353 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c | |||
@@ -48,6 +48,7 @@ | |||
48 | */ | 48 | */ |
49 | 49 | ||
50 | #include <linux/config.h> | 50 | #include <linux/config.h> |
51 | #include <linux/mutex.h> | ||
51 | #include <linux/module.h> | 52 | #include <linux/module.h> |
52 | #include <linux/kernel.h> | 53 | #include <linux/kernel.h> |
53 | #include <linux/signal.h> | 54 | #include <linux/signal.h> |
@@ -69,27 +70,9 @@ | |||
69 | #include <linux/vmalloc.h> | 70 | #include <linux/vmalloc.h> |
70 | 71 | ||
71 | #include "sisusb.h" | 72 | #include "sisusb.h" |
73 | #include "sisusb_init.h" | ||
72 | 74 | ||
73 | #ifdef INCL_SISUSB_CON | 75 | #ifdef INCL_SISUSB_CON |
74 | extern int sisusb_setreg(struct sisusb_usb_data *, int, u8); | ||
75 | extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *); | ||
76 | extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8); | ||
77 | extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *); | ||
78 | extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8); | ||
79 | extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8); | ||
80 | extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8); | ||
81 | |||
82 | extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); | ||
83 | extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); | ||
84 | extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data); | ||
85 | extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data); | ||
86 | extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, | ||
87 | u32 dest, int length, size_t *bytes_written); | ||
88 | |||
89 | extern void sisusb_delete(struct kref *kref); | ||
90 | extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); | ||
91 | |||
92 | extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); | ||
93 | 76 | ||
94 | #define sisusbcon_writew(val, addr) (*(addr) = (val)) | 77 | #define sisusbcon_writew(val, addr) (*(addr) = (val)) |
95 | #define sisusbcon_readw(addr) (*(addr)) | 78 | #define sisusbcon_readw(addr) (*(addr)) |
@@ -102,8 +85,6 @@ static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES]; | |||
102 | /* Forward declaration */ | 85 | /* Forward declaration */ |
103 | static const struct consw sisusb_con; | 86 | static const struct consw sisusb_con; |
104 | 87 | ||
105 | extern struct semaphore disconnect_sem; | ||
106 | |||
107 | static inline void | 88 | static inline void |
108 | sisusbcon_memsetw(u16 *s, u16 c, unsigned int count) | 89 | sisusbcon_memsetw(u16 *s, u16 c, unsigned int count) |
109 | { | 90 | { |
@@ -194,11 +175,11 @@ sisusb_get_sisusb_lock_and_check(unsigned short console) | |||
194 | if (!(sisusb = sisusb_get_sisusb(console))) | 175 | if (!(sisusb = sisusb_get_sisusb(console))) |
195 | return NULL; | 176 | return NULL; |
196 | 177 | ||
197 | down(&sisusb->lock); | 178 | mutex_lock(&sisusb->lock); |
198 | 179 | ||
199 | if (!sisusb_sisusb_valid(sisusb) || | 180 | if (!sisusb_sisusb_valid(sisusb) || |
200 | !sisusb->havethisconsole[console]) { | 181 | !sisusb->havethisconsole[console]) { |
201 | up(&sisusb->lock); | 182 | mutex_unlock(&sisusb->lock); |
202 | return NULL; | 183 | return NULL; |
203 | } | 184 | } |
204 | 185 | ||
@@ -236,18 +217,18 @@ sisusbcon_init(struct vc_data *c, int init) | |||
236 | * are set up/restored. | 217 | * are set up/restored. |
237 | */ | 218 | */ |
238 | 219 | ||
239 | down(&disconnect_sem); | 220 | mutex_lock(&disconnect_mutex); |
240 | 221 | ||
241 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { | 222 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { |
242 | up(&disconnect_sem); | 223 | mutex_unlock(&disconnect_mutex); |
243 | return; | 224 | return; |
244 | } | 225 | } |
245 | 226 | ||
246 | down(&sisusb->lock); | 227 | mutex_lock(&sisusb->lock); |
247 | 228 | ||
248 | if (!sisusb_sisusb_valid(sisusb)) { | 229 | if (!sisusb_sisusb_valid(sisusb)) { |
249 | up(&sisusb->lock); | 230 | mutex_unlock(&sisusb->lock); |
250 | up(&disconnect_sem); | 231 | mutex_unlock(&disconnect_mutex); |
251 | return; | 232 | return; |
252 | } | 233 | } |
253 | 234 | ||
@@ -284,9 +265,9 @@ sisusbcon_init(struct vc_data *c, int init) | |||
284 | if (!*c->vc_uni_pagedir_loc) | 265 | if (!*c->vc_uni_pagedir_loc) |
285 | con_set_default_unimap(c); | 266 | con_set_default_unimap(c); |
286 | 267 | ||
287 | up(&sisusb->lock); | 268 | mutex_unlock(&sisusb->lock); |
288 | 269 | ||
289 | up(&disconnect_sem); | 270 | mutex_unlock(&disconnect_mutex); |
290 | 271 | ||
291 | if (init) { | 272 | if (init) { |
292 | c->vc_cols = cols; | 273 | c->vc_cols = cols; |
@@ -306,14 +287,14 @@ sisusbcon_deinit(struct vc_data *c) | |||
306 | * and others, ie not under our control. | 287 | * and others, ie not under our control. |
307 | */ | 288 | */ |
308 | 289 | ||
309 | down(&disconnect_sem); | 290 | mutex_lock(&disconnect_mutex); |
310 | 291 | ||
311 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { | 292 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { |
312 | up(&disconnect_sem); | 293 | mutex_unlock(&disconnect_mutex); |
313 | return; | 294 | return; |
314 | } | 295 | } |
315 | 296 | ||
316 | down(&sisusb->lock); | 297 | mutex_lock(&sisusb->lock); |
317 | 298 | ||
318 | /* Clear ourselves in mysisusbs */ | 299 | /* Clear ourselves in mysisusbs */ |
319 | mysisusbs[c->vc_num] = NULL; | 300 | mysisusbs[c->vc_num] = NULL; |
@@ -332,12 +313,12 @@ sisusbcon_deinit(struct vc_data *c) | |||
332 | } | 313 | } |
333 | } | 314 | } |
334 | 315 | ||
335 | up(&sisusb->lock); | 316 | mutex_unlock(&sisusb->lock); |
336 | 317 | ||
337 | /* decrement the usage count on our sisusb */ | 318 | /* decrement the usage count on our sisusb */ |
338 | kref_put(&sisusb->kref, sisusb_delete); | 319 | kref_put(&sisusb->kref, sisusb_delete); |
339 | 320 | ||
340 | up(&disconnect_sem); | 321 | mutex_unlock(&disconnect_mutex); |
341 | } | 322 | } |
342 | 323 | ||
343 | /* interface routine */ | 324 | /* interface routine */ |
@@ -417,7 +398,7 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x) | |||
417 | #endif | 398 | #endif |
418 | 399 | ||
419 | if (sisusb_is_inactive(c, sisusb)) { | 400 | if (sisusb_is_inactive(c, sisusb)) { |
420 | up(&sisusb->lock); | 401 | mutex_unlock(&sisusb->lock); |
421 | return; | 402 | return; |
422 | } | 403 | } |
423 | 404 | ||
@@ -425,7 +406,7 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x) | |||
425 | sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y), | 406 | sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y), |
426 | (u32)SISUSB_HADDR(x, y), 2, &written); | 407 | (u32)SISUSB_HADDR(x, y), 2, &written); |
427 | 408 | ||
428 | up(&sisusb->lock); | 409 | mutex_unlock(&sisusb->lock); |
429 | } | 410 | } |
430 | 411 | ||
431 | /* Interface routine */ | 412 | /* Interface routine */ |
@@ -453,14 +434,14 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s, | |||
453 | sisusbcon_writew(sisusbcon_readw(s++), dest++); | 434 | sisusbcon_writew(sisusbcon_readw(s++), dest++); |
454 | 435 | ||
455 | if (sisusb_is_inactive(c, sisusb)) { | 436 | if (sisusb_is_inactive(c, sisusb)) { |
456 | up(&sisusb->lock); | 437 | mutex_unlock(&sisusb->lock); |
457 | return; | 438 | return; |
458 | } | 439 | } |
459 | 440 | ||
460 | sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y), | 441 | sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y), |
461 | (u32)SISUSB_HADDR(x, y), count * 2, &written); | 442 | (u32)SISUSB_HADDR(x, y), count * 2, &written); |
462 | 443 | ||
463 | up(&sisusb->lock); | 444 | mutex_unlock(&sisusb->lock); |
464 | } | 445 | } |
465 | 446 | ||
466 | /* Interface routine */ | 447 | /* Interface routine */ |
@@ -504,7 +485,7 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width) | |||
504 | } | 485 | } |
505 | 486 | ||
506 | if (sisusb_is_inactive(c, sisusb)) { | 487 | if (sisusb_is_inactive(c, sisusb)) { |
507 | up(&sisusb->lock); | 488 | mutex_unlock(&sisusb->lock); |
508 | return; | 489 | return; |
509 | } | 490 | } |
510 | 491 | ||
@@ -514,7 +495,7 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width) | |||
514 | sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y), | 495 | sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y), |
515 | (u32)SISUSB_HADDR(x, y), length, &written); | 496 | (u32)SISUSB_HADDR(x, y), length, &written); |
516 | 497 | ||
517 | up(&sisusb->lock); | 498 | mutex_unlock(&sisusb->lock); |
518 | } | 499 | } |
519 | 500 | ||
520 | /* Interface routine */ | 501 | /* Interface routine */ |
@@ -576,7 +557,7 @@ sisusbcon_bmove(struct vc_data *c, int sy, int sx, | |||
576 | #endif | 557 | #endif |
577 | 558 | ||
578 | if (sisusb_is_inactive(c, sisusb)) { | 559 | if (sisusb_is_inactive(c, sisusb)) { |
579 | up(&sisusb->lock); | 560 | mutex_unlock(&sisusb->lock); |
580 | return; | 561 | return; |
581 | } | 562 | } |
582 | 563 | ||
@@ -586,7 +567,7 @@ sisusbcon_bmove(struct vc_data *c, int sy, int sx, | |||
586 | sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy), | 567 | sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy), |
587 | (u32)SISUSB_HADDR(dx, dy), length, &written); | 568 | (u32)SISUSB_HADDR(dx, dy), length, &written); |
588 | 569 | ||
589 | up(&sisusb->lock); | 570 | mutex_unlock(&sisusb->lock); |
590 | } | 571 | } |
591 | 572 | ||
592 | /* interface routine */ | 573 | /* interface routine */ |
@@ -609,7 +590,7 @@ sisusbcon_switch(struct vc_data *c) | |||
609 | 590 | ||
610 | /* Don't write to screen if in gfx mode */ | 591 | /* Don't write to screen if in gfx mode */ |
611 | if (sisusb_is_inactive(c, sisusb)) { | 592 | if (sisusb_is_inactive(c, sisusb)) { |
612 | up(&sisusb->lock); | 593 | mutex_unlock(&sisusb->lock); |
613 | return 0; | 594 | return 0; |
614 | } | 595 | } |
615 | 596 | ||
@@ -618,7 +599,7 @@ sisusbcon_switch(struct vc_data *c) | |||
618 | * as origin. | 599 | * as origin. |
619 | */ | 600 | */ |
620 | if (c->vc_origin == (unsigned long)c->vc_screenbuf) { | 601 | if (c->vc_origin == (unsigned long)c->vc_screenbuf) { |
621 | up(&sisusb->lock); | 602 | mutex_unlock(&sisusb->lock); |
622 | printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n"); | 603 | printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n"); |
623 | return 0; | 604 | return 0; |
624 | } | 605 | } |
@@ -635,7 +616,7 @@ sisusbcon_switch(struct vc_data *c) | |||
635 | (u32)SISUSB_HADDR(0, 0), | 616 | (u32)SISUSB_HADDR(0, 0), |
636 | length, &written); | 617 | length, &written); |
637 | 618 | ||
638 | up(&sisusb->lock); | 619 | mutex_unlock(&sisusb->lock); |
639 | 620 | ||
640 | return 0; | 621 | return 0; |
641 | } | 622 | } |
@@ -657,7 +638,7 @@ sisusbcon_save_screen(struct vc_data *c) | |||
657 | /* sisusb->lock is down */ | 638 | /* sisusb->lock is down */ |
658 | 639 | ||
659 | if (sisusb_is_inactive(c, sisusb)) { | 640 | if (sisusb_is_inactive(c, sisusb)) { |
660 | up(&sisusb->lock); | 641 | mutex_unlock(&sisusb->lock); |
661 | return; | 642 | return; |
662 | } | 643 | } |
663 | 644 | ||
@@ -669,7 +650,7 @@ sisusbcon_save_screen(struct vc_data *c) | |||
669 | sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin, | 650 | sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin, |
670 | length); | 651 | length); |
671 | 652 | ||
672 | up(&sisusb->lock); | 653 | mutex_unlock(&sisusb->lock); |
673 | } | 654 | } |
674 | 655 | ||
675 | /* interface routine */ | 656 | /* interface routine */ |
@@ -690,7 +671,7 @@ sisusbcon_set_palette(struct vc_data *c, unsigned char *table) | |||
690 | /* sisusb->lock is down */ | 671 | /* sisusb->lock is down */ |
691 | 672 | ||
692 | if (sisusb_is_inactive(c, sisusb)) { | 673 | if (sisusb_is_inactive(c, sisusb)) { |
693 | up(&sisusb->lock); | 674 | mutex_unlock(&sisusb->lock); |
694 | return -EINVAL; | 675 | return -EINVAL; |
695 | } | 676 | } |
696 | 677 | ||
@@ -705,7 +686,7 @@ sisusbcon_set_palette(struct vc_data *c, unsigned char *table) | |||
705 | break; | 686 | break; |
706 | } | 687 | } |
707 | 688 | ||
708 | up(&sisusb->lock); | 689 | mutex_unlock(&sisusb->lock); |
709 | 690 | ||
710 | return 0; | 691 | return 0; |
711 | } | 692 | } |
@@ -728,7 +709,7 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch) | |||
728 | sisusb->is_gfx = blank ? 1 : 0; | 709 | sisusb->is_gfx = blank ? 1 : 0; |
729 | 710 | ||
730 | if (sisusb_is_inactive(c, sisusb)) { | 711 | if (sisusb_is_inactive(c, sisusb)) { |
731 | up(&sisusb->lock); | 712 | mutex_unlock(&sisusb->lock); |
732 | return 0; | 713 | return 0; |
733 | } | 714 | } |
734 | 715 | ||
@@ -777,7 +758,7 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch) | |||
777 | cr63 = 0x40; | 758 | cr63 = 0x40; |
778 | break; | 759 | break; |
779 | default: | 760 | default: |
780 | up(&sisusb->lock); | 761 | mutex_unlock(&sisusb->lock); |
781 | return -EINVAL; | 762 | return -EINVAL; |
782 | } | 763 | } |
783 | 764 | ||
@@ -788,7 +769,7 @@ sisusbcon_blank(struct vc_data *c, int blank, int mode_switch) | |||
788 | 769 | ||
789 | } | 770 | } |
790 | 771 | ||
791 | up(&sisusb->lock); | 772 | mutex_unlock(&sisusb->lock); |
792 | 773 | ||
793 | return ret; | 774 | return ret; |
794 | } | 775 | } |
@@ -809,7 +790,7 @@ sisusbcon_scrolldelta(struct vc_data *c, int lines) | |||
809 | /* sisusb->lock is down */ | 790 | /* sisusb->lock is down */ |
810 | 791 | ||
811 | if (sisusb_is_inactive(c, sisusb)) { | 792 | if (sisusb_is_inactive(c, sisusb)) { |
812 | up(&sisusb->lock); | 793 | mutex_unlock(&sisusb->lock); |
813 | return 0; | 794 | return 0; |
814 | } | 795 | } |
815 | 796 | ||
@@ -849,7 +830,7 @@ sisusbcon_scrolldelta(struct vc_data *c, int lines) | |||
849 | 830 | ||
850 | sisusbcon_set_start_address(sisusb, c); | 831 | sisusbcon_set_start_address(sisusb, c); |
851 | 832 | ||
852 | up(&sisusb->lock); | 833 | mutex_unlock(&sisusb->lock); |
853 | 834 | ||
854 | return 1; | 835 | return 1; |
855 | } | 836 | } |
@@ -867,7 +848,7 @@ sisusbcon_cursor(struct vc_data *c, int mode) | |||
867 | /* sisusb->lock is down */ | 848 | /* sisusb->lock is down */ |
868 | 849 | ||
869 | if (sisusb_is_inactive(c, sisusb)) { | 850 | if (sisusb_is_inactive(c, sisusb)) { |
870 | up(&sisusb->lock); | 851 | mutex_unlock(&sisusb->lock); |
871 | return; | 852 | return; |
872 | } | 853 | } |
873 | 854 | ||
@@ -879,7 +860,7 @@ sisusbcon_cursor(struct vc_data *c, int mode) | |||
879 | if (mode == CM_ERASE) { | 860 | if (mode == CM_ERASE) { |
880 | sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20); | 861 | sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20); |
881 | sisusb->sisusb_cursor_size_to = -1; | 862 | sisusb->sisusb_cursor_size_to = -1; |
882 | up(&sisusb->lock); | 863 | mutex_unlock(&sisusb->lock); |
883 | return; | 864 | return; |
884 | } | 865 | } |
885 | 866 | ||
@@ -919,7 +900,7 @@ sisusbcon_cursor(struct vc_data *c, int mode) | |||
919 | sisusb->sisusb_cursor_size_to = to; | 900 | sisusb->sisusb_cursor_size_to = to; |
920 | } | 901 | } |
921 | 902 | ||
922 | up(&sisusb->lock); | 903 | mutex_unlock(&sisusb->lock); |
923 | } | 904 | } |
924 | 905 | ||
925 | static int | 906 | static int |
@@ -961,7 +942,7 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb, | |||
961 | sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t), | 942 | sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t), |
962 | (u32)SISUSB_HADDR(0, t), length, &written); | 943 | (u32)SISUSB_HADDR(0, t), length, &written); |
963 | 944 | ||
964 | up(&sisusb->lock); | 945 | mutex_unlock(&sisusb->lock); |
965 | 946 | ||
966 | return 1; | 947 | return 1; |
967 | } | 948 | } |
@@ -994,7 +975,7 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) | |||
994 | /* sisusb->lock is down */ | 975 | /* sisusb->lock is down */ |
995 | 976 | ||
996 | if (sisusb_is_inactive(c, sisusb)) { | 977 | if (sisusb_is_inactive(c, sisusb)) { |
997 | up(&sisusb->lock); | 978 | mutex_unlock(&sisusb->lock); |
998 | return 0; | 979 | return 0; |
999 | } | 980 | } |
1000 | 981 | ||
@@ -1084,7 +1065,7 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) | |||
1084 | 1065 | ||
1085 | c->vc_pos = c->vc_pos - oldorigin + c->vc_origin; | 1066 | c->vc_pos = c->vc_pos - oldorigin + c->vc_origin; |
1086 | 1067 | ||
1087 | up(&sisusb->lock); | 1068 | mutex_unlock(&sisusb->lock); |
1088 | 1069 | ||
1089 | return 1; | 1070 | return 1; |
1090 | } | 1071 | } |
@@ -1106,7 +1087,7 @@ sisusbcon_set_origin(struct vc_data *c) | |||
1106 | /* sisusb->lock is down */ | 1087 | /* sisusb->lock is down */ |
1107 | 1088 | ||
1108 | if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) { | 1089 | if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) { |
1109 | up(&sisusb->lock); | 1090 | mutex_unlock(&sisusb->lock); |
1110 | return 0; | 1091 | return 0; |
1111 | } | 1092 | } |
1112 | 1093 | ||
@@ -1116,7 +1097,7 @@ sisusbcon_set_origin(struct vc_data *c) | |||
1116 | 1097 | ||
1117 | sisusb->con_rolled_over = 0; | 1098 | sisusb->con_rolled_over = 0; |
1118 | 1099 | ||
1119 | up(&sisusb->lock); | 1100 | mutex_unlock(&sisusb->lock); |
1120 | 1101 | ||
1121 | return 1; | 1102 | return 1; |
1122 | } | 1103 | } |
@@ -1133,7 +1114,7 @@ sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows) | |||
1133 | 1114 | ||
1134 | fh = sisusb->current_font_height; | 1115 | fh = sisusb->current_font_height; |
1135 | 1116 | ||
1136 | up(&sisusb->lock); | 1117 | mutex_unlock(&sisusb->lock); |
1137 | 1118 | ||
1138 | /* We are quite unflexible as regards resizing. The vt code | 1119 | /* We are quite unflexible as regards resizing. The vt code |
1139 | * handles sizes where the line length isn't equal the pitch | 1120 | * handles sizes where the line length isn't equal the pitch |
@@ -1167,7 +1148,7 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, | |||
1167 | 1148 | ||
1168 | if ((slot != 0 && slot != 2) || !fh) { | 1149 | if ((slot != 0 && slot != 2) || !fh) { |
1169 | if (uplock) | 1150 | if (uplock) |
1170 | up(&sisusb->lock); | 1151 | mutex_unlock(&sisusb->lock); |
1171 | return -EINVAL; | 1152 | return -EINVAL; |
1172 | } | 1153 | } |
1173 | 1154 | ||
@@ -1327,7 +1308,7 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, | |||
1327 | } | 1308 | } |
1328 | 1309 | ||
1329 | if (uplock) | 1310 | if (uplock) |
1330 | up(&sisusb->lock); | 1311 | mutex_unlock(&sisusb->lock); |
1331 | 1312 | ||
1332 | if (dorecalc && c) { | 1313 | if (dorecalc && c) { |
1333 | int i, rows = c->vc_scan_lines / fh; | 1314 | int i, rows = c->vc_scan_lines / fh; |
@@ -1351,7 +1332,7 @@ sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, | |||
1351 | 1332 | ||
1352 | font_op_error: | 1333 | font_op_error: |
1353 | if (uplock) | 1334 | if (uplock) |
1354 | up(&sisusb->lock); | 1335 | mutex_unlock(&sisusb->lock); |
1355 | 1336 | ||
1356 | return -EIO; | 1337 | return -EIO; |
1357 | } | 1338 | } |
@@ -1417,19 +1398,19 @@ sisusbcon_font_get(struct vc_data *c, struct console_font *font) | |||
1417 | font->charcount = 256; | 1398 | font->charcount = 256; |
1418 | 1399 | ||
1419 | if (!font->data) { | 1400 | if (!font->data) { |
1420 | up(&sisusb->lock); | 1401 | mutex_unlock(&sisusb->lock); |
1421 | return 0; | 1402 | return 0; |
1422 | } | 1403 | } |
1423 | 1404 | ||
1424 | if (!sisusb->font_backup) { | 1405 | if (!sisusb->font_backup) { |
1425 | up(&sisusb->lock); | 1406 | mutex_unlock(&sisusb->lock); |
1426 | return -ENODEV; | 1407 | return -ENODEV; |
1427 | } | 1408 | } |
1428 | 1409 | ||
1429 | /* Copy 256 chars only, like vgacon */ | 1410 | /* Copy 256 chars only, like vgacon */ |
1430 | memcpy(font->data, sisusb->font_backup, 256 * 32); | 1411 | memcpy(font->data, sisusb->font_backup, 256 * 32); |
1431 | 1412 | ||
1432 | up(&sisusb->lock); | 1413 | mutex_unlock(&sisusb->lock); |
1433 | 1414 | ||
1434 | return 0; | 1415 | return 0; |
1435 | } | 1416 | } |
@@ -1486,7 +1467,7 @@ static int sisusbdummycon_dummy(void) | |||
1486 | 1467 | ||
1487 | #define SISUSBCONDUMMY (void *)sisusbdummycon_dummy | 1468 | #define SISUSBCONDUMMY (void *)sisusbdummycon_dummy |
1488 | 1469 | ||
1489 | const struct consw sisusb_dummy_con = { | 1470 | static const struct consw sisusb_dummy_con = { |
1490 | .owner = THIS_MODULE, | 1471 | .owner = THIS_MODULE, |
1491 | .con_startup = sisusbdummycon_startup, | 1472 | .con_startup = sisusbdummycon_startup, |
1492 | .con_init = sisusbdummycon_init, | 1473 | .con_init = sisusbdummycon_init, |
@@ -1512,14 +1493,14 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1512 | { | 1493 | { |
1513 | int i, ret, minor = sisusb->minor; | 1494 | int i, ret, minor = sisusb->minor; |
1514 | 1495 | ||
1515 | down(&disconnect_sem); | 1496 | mutex_lock(&disconnect_mutex); |
1516 | 1497 | ||
1517 | down(&sisusb->lock); | 1498 | mutex_lock(&sisusb->lock); |
1518 | 1499 | ||
1519 | /* Erm.. that should not happen */ | 1500 | /* Erm.. that should not happen */ |
1520 | if (sisusb->haveconsole || !sisusb->SiS_Pr) { | 1501 | if (sisusb->haveconsole || !sisusb->SiS_Pr) { |
1521 | up(&sisusb->lock); | 1502 | mutex_unlock(&sisusb->lock); |
1522 | up(&disconnect_sem); | 1503 | mutex_unlock(&disconnect_mutex); |
1523 | return 1; | 1504 | return 1; |
1524 | } | 1505 | } |
1525 | 1506 | ||
@@ -1529,15 +1510,15 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1529 | if (first > last || | 1510 | if (first > last || |
1530 | first > MAX_NR_CONSOLES || | 1511 | first > MAX_NR_CONSOLES || |
1531 | last > MAX_NR_CONSOLES) { | 1512 | last > MAX_NR_CONSOLES) { |
1532 | up(&sisusb->lock); | 1513 | mutex_unlock(&sisusb->lock); |
1533 | up(&disconnect_sem); | 1514 | mutex_unlock(&disconnect_mutex); |
1534 | return 1; | 1515 | return 1; |
1535 | } | 1516 | } |
1536 | 1517 | ||
1537 | /* If gfxcore not initialized or no consoles given, quit graciously */ | 1518 | /* If gfxcore not initialized or no consoles given, quit graciously */ |
1538 | if (!sisusb->gfxinit || first < 1 || last < 1) { | 1519 | if (!sisusb->gfxinit || first < 1 || last < 1) { |
1539 | up(&sisusb->lock); | 1520 | mutex_unlock(&sisusb->lock); |
1540 | up(&disconnect_sem); | 1521 | mutex_unlock(&disconnect_mutex); |
1541 | return 0; | 1522 | return 0; |
1542 | } | 1523 | } |
1543 | 1524 | ||
@@ -1547,8 +1528,8 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1547 | 1528 | ||
1548 | /* Set up text mode (and upload default font) */ | 1529 | /* Set up text mode (and upload default font) */ |
1549 | if (sisusb_reset_text_mode(sisusb, 1)) { | 1530 | if (sisusb_reset_text_mode(sisusb, 1)) { |
1550 | up(&sisusb->lock); | 1531 | mutex_unlock(&sisusb->lock); |
1551 | up(&disconnect_sem); | 1532 | mutex_unlock(&disconnect_mutex); |
1552 | printk(KERN_ERR | 1533 | printk(KERN_ERR |
1553 | "sisusbvga[%d]: Failed to set up text mode\n", | 1534 | "sisusbvga[%d]: Failed to set up text mode\n", |
1554 | minor); | 1535 | minor); |
@@ -1571,16 +1552,16 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1571 | 1552 | ||
1572 | /* Allocate screen buffer */ | 1553 | /* Allocate screen buffer */ |
1573 | if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { | 1554 | if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { |
1574 | up(&sisusb->lock); | 1555 | mutex_unlock(&sisusb->lock); |
1575 | up(&disconnect_sem); | 1556 | mutex_unlock(&disconnect_mutex); |
1576 | printk(KERN_ERR | 1557 | printk(KERN_ERR |
1577 | "sisusbvga[%d]: Failed to allocate screen buffer\n", | 1558 | "sisusbvga[%d]: Failed to allocate screen buffer\n", |
1578 | minor); | 1559 | minor); |
1579 | return 1; | 1560 | return 1; |
1580 | } | 1561 | } |
1581 | 1562 | ||
1582 | up(&sisusb->lock); | 1563 | mutex_unlock(&sisusb->lock); |
1583 | up(&disconnect_sem); | 1564 | mutex_unlock(&disconnect_mutex); |
1584 | 1565 | ||
1585 | /* Now grab the desired console(s) */ | 1566 | /* Now grab the desired console(s) */ |
1586 | ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); | 1567 | ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); |
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c index 044fa4482f9f..968f0d38cff7 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.c +++ b/drivers/usb/misc/sisusbvga/sisusb_init.c | |||
@@ -74,6 +74,7 @@ SiSUSB_InitPtr(struct SiS_Private *SiS_Pr) | |||
74 | /* HELPER: Get ModeID */ | 74 | /* HELPER: Get ModeID */ |
75 | /*********************************************/ | 75 | /*********************************************/ |
76 | 76 | ||
77 | #if 0 | ||
77 | unsigned short | 78 | unsigned short |
78 | SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth) | 79 | SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth) |
79 | { | 80 | { |
@@ -157,6 +158,7 @@ SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth) | |||
157 | 158 | ||
158 | return ModeIndex; | 159 | return ModeIndex; |
159 | } | 160 | } |
161 | #endif /* 0 */ | ||
160 | 162 | ||
161 | /*********************************************/ | 163 | /*********************************************/ |
162 | /* HELPER: SetReg, GetReg */ | 164 | /* HELPER: SetReg, GetReg */ |
@@ -233,7 +235,7 @@ SiS_DisplayOn(struct SiS_Private *SiS_Pr) | |||
233 | /* HELPER: Init Port Addresses */ | 235 | /* HELPER: Init Port Addresses */ |
234 | /*********************************************/ | 236 | /*********************************************/ |
235 | 237 | ||
236 | void | 238 | static void |
237 | SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr) | 239 | SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr) |
238 | { | 240 | { |
239 | SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; | 241 | SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; |
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h index 5b11577835c8..f05f83268af4 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.h +++ b/drivers/usb/misc/sisusbvga/sisusb_init.h | |||
@@ -690,7 +690,7 @@ static const struct SiS_CRT1Table SiSUSB_CRT1Table[] = | |||
690 | 0x41}} /* 0x54 */ | 690 | 0x41}} /* 0x54 */ |
691 | }; | 691 | }; |
692 | 692 | ||
693 | static struct SiS_VCLKData SiSUSB_VCLKData[] = | 693 | static const struct SiS_VCLKData SiSUSB_VCLKData[] = |
694 | { | 694 | { |
695 | { 0x1b,0xe1, 25}, /* 0x00 */ | 695 | { 0x1b,0xe1, 25}, /* 0x00 */ |
696 | { 0x4e,0xe4, 28}, /* 0x01 */ | 696 | { 0x4e,0xe4, 28}, /* 0x01 */ |
@@ -808,8 +808,8 @@ static struct SiS_VCLKData SiSUSB_VCLKData[] = | |||
808 | { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ | 808 | { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ |
809 | }; | 809 | }; |
810 | 810 | ||
811 | void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr); | 811 | extern struct mutex disconnect_mutex; |
812 | unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth); | 812 | |
813 | int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); | 813 | int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); |
814 | int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); | 814 | int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); |
815 | 815 | ||
@@ -826,5 +826,19 @@ extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, | |||
826 | extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, | 826 | extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, |
827 | u8 idx, u8 myand); | 827 | u8 idx, u8 myand); |
828 | 828 | ||
829 | void sisusb_delete(struct kref *kref); | ||
830 | int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); | ||
831 | int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); | ||
832 | int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, | ||
833 | u32 dest, int length, size_t *bytes_written); | ||
834 | int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); | ||
835 | int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, | ||
836 | u8 *arg, int cmapsz, int ch512, int dorecalc, | ||
837 | struct vc_data *c, int fh, int uplock); | ||
838 | void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location); | ||
839 | int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last); | ||
840 | void sisusb_console_exit(struct sisusb_usb_data *sisusb); | ||
841 | void sisusb_init_concode(void); | ||
842 | |||
829 | #endif | 843 | #endif |
830 | 844 | ||
diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h index 94edd4726c42..f325ecb29a61 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_struct.h +++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h | |||
@@ -161,7 +161,7 @@ struct SiS_Private | |||
161 | const struct SiS_Ext *SiS_EModeIDTable; | 161 | const struct SiS_Ext *SiS_EModeIDTable; |
162 | const struct SiS_Ext2 *SiS_RefIndex; | 162 | const struct SiS_Ext2 *SiS_RefIndex; |
163 | const struct SiS_CRT1Table *SiS_CRT1Table; | 163 | const struct SiS_CRT1Table *SiS_CRT1Table; |
164 | struct SiS_VCLKData *SiS_VCLKData; | 164 | const struct SiS_VCLKData *SiS_VCLKData; |
165 | const struct SiS_ModeResInfo *SiS_ModeResInfo; | 165 | const struct SiS_ModeResInfo *SiS_ModeResInfo; |
166 | }; | 166 | }; |
167 | 167 | ||
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index ccc5e8238bd8..81ba14c73dc7 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -802,7 +802,9 @@ error: | |||
802 | 802 | ||
803 | if (u == urb || !u->dev) | 803 | if (u == urb || !u->dev) |
804 | continue; | 804 | continue; |
805 | spin_unlock(&ctx->lock); | ||
805 | status = usb_unlink_urb (u); | 806 | status = usb_unlink_urb (u); |
807 | spin_lock(&ctx->lock); | ||
806 | switch (status) { | 808 | switch (status) { |
807 | case -EINPROGRESS: | 809 | case -EINPROGRESS: |
808 | case -EBUSY: | 810 | case -EBUSY: |
@@ -1335,7 +1337,9 @@ struct iso_context { | |||
1335 | unsigned pending; | 1337 | unsigned pending; |
1336 | spinlock_t lock; | 1338 | spinlock_t lock; |
1337 | struct completion done; | 1339 | struct completion done; |
1340 | int submit_error; | ||
1338 | unsigned long errors; | 1341 | unsigned long errors; |
1342 | unsigned long packet_count; | ||
1339 | struct usbtest_dev *dev; | 1343 | struct usbtest_dev *dev; |
1340 | }; | 1344 | }; |
1341 | 1345 | ||
@@ -1346,10 +1350,14 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs) | |||
1346 | spin_lock(&ctx->lock); | 1350 | spin_lock(&ctx->lock); |
1347 | ctx->count--; | 1351 | ctx->count--; |
1348 | 1352 | ||
1353 | ctx->packet_count += urb->number_of_packets; | ||
1349 | if (urb->error_count > 0) | 1354 | if (urb->error_count > 0) |
1350 | ctx->errors += urb->error_count; | 1355 | ctx->errors += urb->error_count; |
1356 | else if (urb->status != 0) | ||
1357 | ctx->errors += urb->number_of_packets; | ||
1351 | 1358 | ||
1352 | if (urb->status == 0 && ctx->count > (ctx->pending - 1)) { | 1359 | if (urb->status == 0 && ctx->count > (ctx->pending - 1) |
1360 | && !ctx->submit_error) { | ||
1353 | int status = usb_submit_urb (urb, GFP_ATOMIC); | 1361 | int status = usb_submit_urb (urb, GFP_ATOMIC); |
1354 | switch (status) { | 1362 | switch (status) { |
1355 | case 0: | 1363 | case 0: |
@@ -1360,6 +1368,8 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs) | |||
1360 | status); | 1368 | status); |
1361 | /* FALLTHROUGH */ | 1369 | /* FALLTHROUGH */ |
1362 | case -ENODEV: /* disconnected */ | 1370 | case -ENODEV: /* disconnected */ |
1371 | case -ESHUTDOWN: /* endpoint disabled */ | ||
1372 | ctx->submit_error = 1; | ||
1363 | break; | 1373 | break; |
1364 | } | 1374 | } |
1365 | } | 1375 | } |
@@ -1369,8 +1379,8 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs) | |||
1369 | if (ctx->pending == 0) { | 1379 | if (ctx->pending == 0) { |
1370 | if (ctx->errors) | 1380 | if (ctx->errors) |
1371 | dev_dbg (&ctx->dev->intf->dev, | 1381 | dev_dbg (&ctx->dev->intf->dev, |
1372 | "iso test, %lu errors\n", | 1382 | "iso test, %lu errors out of %lu\n", |
1373 | ctx->errors); | 1383 | ctx->errors, ctx->packet_count); |
1374 | complete (&ctx->done); | 1384 | complete (&ctx->done); |
1375 | } | 1385 | } |
1376 | done: | 1386 | done: |
@@ -1431,15 +1441,14 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, | |||
1431 | struct usb_device *udev; | 1441 | struct usb_device *udev; |
1432 | unsigned i; | 1442 | unsigned i; |
1433 | unsigned long packets = 0; | 1443 | unsigned long packets = 0; |
1434 | int status; | 1444 | int status = 0; |
1435 | struct urb *urbs[10]; /* FIXME no limit */ | 1445 | struct urb *urbs[10]; /* FIXME no limit */ |
1436 | 1446 | ||
1437 | if (param->sglen > 10) | 1447 | if (param->sglen > 10) |
1438 | return -EDOM; | 1448 | return -EDOM; |
1439 | 1449 | ||
1450 | memset(&context, 0, sizeof context); | ||
1440 | context.count = param->iterations * param->sglen; | 1451 | context.count = param->iterations * param->sglen; |
1441 | context.pending = param->sglen; | ||
1442 | context.errors = 0; | ||
1443 | context.dev = dev; | 1452 | context.dev = dev; |
1444 | init_completion (&context.done); | 1453 | init_completion (&context.done); |
1445 | spin_lock_init (&context.lock); | 1454 | spin_lock_init (&context.lock); |
@@ -1471,6 +1480,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, | |||
1471 | 1480 | ||
1472 | spin_lock_irq (&context.lock); | 1481 | spin_lock_irq (&context.lock); |
1473 | for (i = 0; i < param->sglen; i++) { | 1482 | for (i = 0; i < param->sglen; i++) { |
1483 | ++context.pending; | ||
1474 | status = usb_submit_urb (urbs [i], SLAB_ATOMIC); | 1484 | status = usb_submit_urb (urbs [i], SLAB_ATOMIC); |
1475 | if (status < 0) { | 1485 | if (status < 0) { |
1476 | ERROR (dev, "submit iso[%d], error %d\n", i, status); | 1486 | ERROR (dev, "submit iso[%d], error %d\n", i, status); |
@@ -1481,12 +1491,26 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, | |||
1481 | 1491 | ||
1482 | simple_free_urb (urbs [i]); | 1492 | simple_free_urb (urbs [i]); |
1483 | context.pending--; | 1493 | context.pending--; |
1494 | context.submit_error = 1; | ||
1495 | break; | ||
1484 | } | 1496 | } |
1485 | } | 1497 | } |
1486 | spin_unlock_irq (&context.lock); | 1498 | spin_unlock_irq (&context.lock); |
1487 | 1499 | ||
1488 | wait_for_completion (&context.done); | 1500 | wait_for_completion (&context.done); |
1489 | return 0; | 1501 | |
1502 | /* | ||
1503 | * Isochronous transfers are expected to fail sometimes. As an | ||
1504 | * arbitrary limit, we will report an error if any submissions | ||
1505 | * fail or if the transfer failure rate is > 10%. | ||
1506 | */ | ||
1507 | if (status != 0) | ||
1508 | ; | ||
1509 | else if (context.submit_error) | ||
1510 | status = -EACCES; | ||
1511 | else if (context.errors > context.packet_count / 10) | ||
1512 | status = -EIO; | ||
1513 | return status; | ||
1490 | 1514 | ||
1491 | fail: | 1515 | fail: |
1492 | for (i = 0; i < param->sglen; i++) { | 1516 | for (i = 0; i < param->sglen; i++) { |
diff --git a/drivers/usb/mon/mon_dma.c b/drivers/usb/mon/mon_dma.c index 0a1367b760a0..ddcfc01e77a0 100644 --- a/drivers/usb/mon/mon_dma.c +++ b/drivers/usb/mon/mon_dma.c | |||
@@ -13,7 +13,10 @@ | |||
13 | #include <linux/usb.h> /* Only needed for declarations in usb_mon.h */ | 13 | #include <linux/usb.h> /* Only needed for declarations in usb_mon.h */ |
14 | #include "usb_mon.h" | 14 | #include "usb_mon.h" |
15 | 15 | ||
16 | #ifdef __i386__ /* CONFIG_ARCH_I386 does not exit */ | 16 | /* |
17 | * PC-compatibles, are, fortunately, sufficiently cache-coherent for this. | ||
18 | */ | ||
19 | #if defined(__i386__) || defined(__x86_64__) /* CONFIG_ARCH_I386 doesn't exit */ | ||
17 | #define MON_HAS_UNMAP 1 | 20 | #define MON_HAS_UNMAP 1 |
18 | 21 | ||
19 | #define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT) | 22 | #define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT) |
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 6ecc27302211..275a66f83058 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c | |||
@@ -97,6 +97,7 @@ static void mon_submit(struct usb_bus *ubus, struct urb *urb) | |||
97 | if (mbus->nreaders == 0) | 97 | if (mbus->nreaders == 0) |
98 | goto out_locked; | 98 | goto out_locked; |
99 | 99 | ||
100 | mbus->cnt_events++; | ||
100 | list_for_each (pos, &mbus->r_list) { | 101 | list_for_each (pos, &mbus->r_list) { |
101 | r = list_entry(pos, struct mon_reader, r_link); | 102 | r = list_entry(pos, struct mon_reader, r_link); |
102 | r->rnf_submit(r->r_data, urb); | 103 | r->rnf_submit(r->r_data, urb); |
@@ -113,20 +114,32 @@ out_unlocked: | |||
113 | 114 | ||
114 | /* | 115 | /* |
115 | */ | 116 | */ |
116 | static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int err) | 117 | static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error) |
117 | { | 118 | { |
118 | struct mon_bus *mbus; | 119 | struct mon_bus *mbus; |
120 | unsigned long flags; | ||
121 | struct list_head *pos; | ||
122 | struct mon_reader *r; | ||
119 | 123 | ||
120 | mbus = ubus->mon_bus; | 124 | mbus = ubus->mon_bus; |
121 | if (mbus == NULL) | 125 | if (mbus == NULL) |
122 | goto out_unlocked; | 126 | goto out_unlocked; |
123 | 127 | ||
124 | /* | 128 | spin_lock_irqsave(&mbus->lock, flags); |
125 | * XXX Capture the error code and the 'E' event. | 129 | if (mbus->nreaders == 0) |
126 | */ | 130 | goto out_locked; |
127 | 131 | ||
132 | mbus->cnt_events++; | ||
133 | list_for_each (pos, &mbus->r_list) { | ||
134 | r = list_entry(pos, struct mon_reader, r_link); | ||
135 | r->rnf_error(r->r_data, urb, error); | ||
136 | } | ||
137 | |||
138 | spin_unlock_irqrestore(&mbus->lock, flags); | ||
128 | return; | 139 | return; |
129 | 140 | ||
141 | out_locked: | ||
142 | spin_unlock_irqrestore(&mbus->lock, flags); | ||
130 | out_unlocked: | 143 | out_unlocked: |
131 | return; | 144 | return; |
132 | } | 145 | } |
@@ -152,6 +165,7 @@ static void mon_complete(struct usb_bus *ubus, struct urb *urb) | |||
152 | } | 165 | } |
153 | 166 | ||
154 | spin_lock_irqsave(&mbus->lock, flags); | 167 | spin_lock_irqsave(&mbus->lock, flags); |
168 | mbus->cnt_events++; | ||
155 | list_for_each (pos, &mbus->r_list) { | 169 | list_for_each (pos, &mbus->r_list) { |
156 | r = list_entry(pos, struct mon_reader, r_link); | 170 | r = list_entry(pos, struct mon_reader, r_link); |
157 | r->rnf_complete(r->r_data, urb); | 171 | r->rnf_complete(r->r_data, urb); |
@@ -163,7 +177,6 @@ static void mon_complete(struct usb_bus *ubus, struct urb *urb) | |||
163 | 177 | ||
164 | /* | 178 | /* |
165 | * Stop monitoring. | 179 | * Stop monitoring. |
166 | * Obviously this must be well locked, so no need to play with mb's. | ||
167 | */ | 180 | */ |
168 | static void mon_stop(struct mon_bus *mbus) | 181 | static void mon_stop(struct mon_bus *mbus) |
169 | { | 182 | { |
diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c index 6e4b165d070a..1fe01d994a79 100644 --- a/drivers/usb/mon/mon_stat.c +++ b/drivers/usb/mon/mon_stat.c | |||
@@ -31,8 +31,8 @@ static int mon_stat_open(struct inode *inode, struct file *file) | |||
31 | mbus = inode->u.generic_ip; | 31 | mbus = inode->u.generic_ip; |
32 | 32 | ||
33 | sp->slen = snprintf(sp->str, STAT_BUF_SIZE, | 33 | sp->slen = snprintf(sp->str, STAT_BUF_SIZE, |
34 | "nreaders %d text_lost %u\n", | 34 | "nreaders %d events %u text_lost %u\n", |
35 | mbus->nreaders, mbus->cnt_text_lost); | 35 | mbus->nreaders, mbus->cnt_events, mbus->cnt_text_lost); |
36 | 36 | ||
37 | file->private_data = sp; | 37 | file->private_data = sp; |
38 | return 0; | 38 | return 0; |
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index ac043ec2b8dc..e02c1a30c4cd 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -26,10 +26,13 @@ | |||
26 | 26 | ||
27 | /* | 27 | /* |
28 | * This limit exists to prevent OOMs when the user process stops reading. | 28 | * This limit exists to prevent OOMs when the user process stops reading. |
29 | * If usbmon were available to unprivileged processes, it might be open | ||
30 | * to a local DoS. But we have to keep to root in order to prevent | ||
31 | * password sniffing from HID devices. | ||
29 | */ | 32 | */ |
30 | #define EVENT_MAX 25 | 33 | #define EVENT_MAX (2*PAGE_SIZE / sizeof(struct mon_event_text)) |
31 | 34 | ||
32 | #define PRINTF_DFL 130 | 35 | #define PRINTF_DFL 160 |
33 | 36 | ||
34 | struct mon_event_text { | 37 | struct mon_event_text { |
35 | struct list_head e_link; | 38 | struct list_head e_link; |
@@ -111,7 +114,7 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | |||
111 | * number of corner cases, but it seems that the following is | 114 | * number of corner cases, but it seems that the following is |
112 | * more or less safe. | 115 | * more or less safe. |
113 | * | 116 | * |
114 | * We do not even try to look transfer_buffer, because it can | 117 | * We do not even try to look at transfer_buffer, because it can |
115 | * contain non-NULL garbage in case the upper level promised to | 118 | * contain non-NULL garbage in case the upper level promised to |
116 | * set DMA for the HCD. | 119 | * set DMA for the HCD. |
117 | */ | 120 | */ |
@@ -179,6 +182,32 @@ static void mon_text_complete(void *data, struct urb *urb) | |||
179 | mon_text_event(rp, urb, 'C'); | 182 | mon_text_event(rp, urb, 'C'); |
180 | } | 183 | } |
181 | 184 | ||
185 | static void mon_text_error(void *data, struct urb *urb, int error) | ||
186 | { | ||
187 | struct mon_reader_text *rp = data; | ||
188 | struct mon_event_text *ep; | ||
189 | |||
190 | if (rp->nevents >= EVENT_MAX || | ||
191 | (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) { | ||
192 | rp->r.m_bus->cnt_text_lost++; | ||
193 | return; | ||
194 | } | ||
195 | |||
196 | ep->type = 'E'; | ||
197 | ep->pipe = urb->pipe; | ||
198 | ep->id = (unsigned long) urb; | ||
199 | ep->tstamp = 0; | ||
200 | ep->length = 0; | ||
201 | ep->status = error; | ||
202 | |||
203 | ep->setup_flag = '-'; | ||
204 | ep->data_flag = 'E'; | ||
205 | |||
206 | rp->nevents++; | ||
207 | list_add_tail(&ep->e_link, &rp->e_list); | ||
208 | wake_up(&rp->wait); | ||
209 | } | ||
210 | |||
182 | /* | 211 | /* |
183 | * Fetch next event from the circular buffer. | 212 | * Fetch next event from the circular buffer. |
184 | */ | 213 | */ |
@@ -232,6 +261,7 @@ static int mon_text_open(struct inode *inode, struct file *file) | |||
232 | rp->r.m_bus = mbus; | 261 | rp->r.m_bus = mbus; |
233 | rp->r.r_data = rp; | 262 | rp->r.r_data = rp; |
234 | rp->r.rnf_submit = mon_text_submit; | 263 | rp->r.rnf_submit = mon_text_submit; |
264 | rp->r.rnf_error = mon_text_error; | ||
235 | rp->r.rnf_complete = mon_text_complete; | 265 | rp->r.rnf_complete = mon_text_complete; |
236 | 266 | ||
237 | snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum, | 267 | snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum, |
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h index 8e0613c350cc..33678c24ebee 100644 --- a/drivers/usb/mon/usb_mon.h +++ b/drivers/usb/mon/usb_mon.h | |||
@@ -27,6 +27,7 @@ struct mon_bus { | |||
27 | struct kref ref; /* Under mon_lock */ | 27 | struct kref ref; /* Under mon_lock */ |
28 | 28 | ||
29 | /* Stats */ | 29 | /* Stats */ |
30 | unsigned int cnt_events; | ||
30 | unsigned int cnt_text_lost; | 31 | unsigned int cnt_text_lost; |
31 | }; | 32 | }; |
32 | 33 | ||
@@ -39,6 +40,7 @@ struct mon_reader { | |||
39 | void *r_data; /* Use container_of instead? */ | 40 | void *r_data; /* Use container_of instead? */ |
40 | 41 | ||
41 | void (*rnf_submit)(void *data, struct urb *urb); | 42 | void (*rnf_submit)(void *data, struct urb *urb); |
43 | void (*rnf_error)(void *data, struct urb *urb, int error); | ||
42 | void (*rnf_complete)(void *data, struct urb *urb); | 44 | void (*rnf_complete)(void *data, struct urb *urb); |
43 | }; | 45 | }; |
44 | 46 | ||
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index efd6ca7e4ac5..054059632a21 100644 --- a/drivers/usb/net/Kconfig +++ b/drivers/usb/net/Kconfig | |||
@@ -301,21 +301,4 @@ config USB_NET_ZAURUS | |||
301 | some cases CDC MDLM) protocol, not "g_ether". | 301 | some cases CDC MDLM) protocol, not "g_ether". |
302 | 302 | ||
303 | 303 | ||
304 | config USB_ZD1201 | ||
305 | tristate "USB ZD1201 based Wireless device support" | ||
306 | depends on NET_RADIO | ||
307 | select FW_LOADER | ||
308 | ---help--- | ||
309 | Say Y if you want to use wireless LAN adapters based on the ZyDAS | ||
310 | ZD1201 chip. | ||
311 | |||
312 | This driver makes the adapter appear as a normal Ethernet interface, | ||
313 | typically on wlan0. | ||
314 | |||
315 | The zd1201 device requires external firmware to be loaded. | ||
316 | This can be found at http://linux-lc100020.sourceforge.net/ | ||
317 | |||
318 | To compile this driver as a module, choose M here: the | ||
319 | module will be called zd1201. | ||
320 | |||
321 | endmenu | 304 | endmenu |
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile index a21e6eaabaf6..160f19dbdf12 100644 --- a/drivers/usb/net/Makefile +++ b/drivers/usb/net/Makefile | |||
@@ -15,7 +15,6 @@ obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o | |||
15 | obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o | 15 | obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o |
16 | obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o | 16 | obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o |
17 | obj-$(CONFIG_USB_USBNET) += usbnet.o | 17 | obj-$(CONFIG_USB_USBNET) += usbnet.o |
18 | obj-$(CONFIG_USB_ZD1201) += zd1201.o | ||
19 | 18 | ||
20 | ifeq ($(CONFIG_USB_DEBUG),y) | 19 | ifeq ($(CONFIG_USB_DEBUG),y) |
21 | EXTRA_CFLAGS += -DDEBUG | 20 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 12b599a0b539..37111acec875 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c | |||
@@ -912,6 +912,10 @@ static const struct usb_device_id products [] = { | |||
912 | USB_DEVICE (0x0b95, 0x7720), | 912 | USB_DEVICE (0x0b95, 0x7720), |
913 | .driver_info = (unsigned long) &ax88772_info, | 913 | .driver_info = (unsigned long) &ax88772_info, |
914 | }, { | 914 | }, { |
915 | // ASIX AX88178 10/100/1000 | ||
916 | USB_DEVICE (0x0b95, 0x1780), | ||
917 | .driver_info = (unsigned long) &ax88772_info, | ||
918 | }, { | ||
915 | // Linksys USB200M Rev 2 | 919 | // Linksys USB200M Rev 2 |
916 | USB_DEVICE (0x13b1, 0x0018), | 920 | USB_DEVICE (0x13b1, 0x0018), |
917 | .driver_info = (unsigned long) &ax88772_info, | 921 | .driver_info = (unsigned long) &ax88772_info, |
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c index 63f1f3ba8e0b..efd195b5912c 100644 --- a/drivers/usb/net/cdc_ether.c +++ b/drivers/usb/net/cdc_ether.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/workqueue.h> | 31 | #include <linux/workqueue.h> |
32 | #include <linux/mii.h> | 32 | #include <linux/mii.h> |
33 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
34 | #include <linux/usb_cdc.h> | 34 | #include <linux/usb/cdc.h> |
35 | 35 | ||
36 | #include "usbnet.h" | 36 | #include "usbnet.h" |
37 | 37 | ||
@@ -455,6 +455,18 @@ static const struct usb_device_id products [] = { | |||
455 | .driver_info = 0, | 455 | .driver_info = 0, |
456 | }, | 456 | }, |
457 | 457 | ||
458 | /* Olympus has some models with a Zaurus-compatible option. | ||
459 | * R-1000 uses a FreeScale i.MXL cpu (ARMv4T) | ||
460 | */ | ||
461 | { | ||
462 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | ||
463 | | USB_DEVICE_ID_MATCH_DEVICE, | ||
464 | .idVendor = 0x07B4, | ||
465 | .idProduct = 0x0F02, /* R-1000 */ | ||
466 | ZAURUS_MASTER_INTERFACE, | ||
467 | .driver_info = 0, | ||
468 | }, | ||
469 | |||
458 | /* | 470 | /* |
459 | * WHITELIST!!! | 471 | * WHITELIST!!! |
460 | * | 472 | * |
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 7683926a1b6f..ab21f960d255 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c | |||
@@ -163,6 +163,8 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, | |||
163 | 163 | ||
164 | /* using ATOMIC, we'd never wake up if we slept */ | 164 | /* using ATOMIC, we'd never wake up if we slept */ |
165 | if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { | 165 | if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { |
166 | if (ret == -ENODEV) | ||
167 | netif_device_detach(pegasus->net); | ||
166 | if (netif_msg_drv(pegasus)) | 168 | if (netif_msg_drv(pegasus)) |
167 | dev_err(&pegasus->intf->dev, "%s, status %d\n", | 169 | dev_err(&pegasus->intf->dev, "%s, status %d\n", |
168 | __FUNCTION__, ret); | 170 | __FUNCTION__, ret); |
@@ -217,6 +219,8 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, | |||
217 | set_current_state(TASK_UNINTERRUPTIBLE); | 219 | set_current_state(TASK_UNINTERRUPTIBLE); |
218 | 220 | ||
219 | if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { | 221 | if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { |
222 | if (ret == -ENODEV) | ||
223 | netif_device_detach(pegasus->net); | ||
220 | if (netif_msg_drv(pegasus)) | 224 | if (netif_msg_drv(pegasus)) |
221 | dev_err(&pegasus->intf->dev, "%s, status %d\n", | 225 | dev_err(&pegasus->intf->dev, "%s, status %d\n", |
222 | __FUNCTION__, ret); | 226 | __FUNCTION__, ret); |
@@ -268,6 +272,8 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) | |||
268 | set_current_state(TASK_UNINTERRUPTIBLE); | 272 | set_current_state(TASK_UNINTERRUPTIBLE); |
269 | 273 | ||
270 | if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { | 274 | if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { |
275 | if (ret == -ENODEV) | ||
276 | netif_device_detach(pegasus->net); | ||
271 | if (netif_msg_drv(pegasus)) | 277 | if (netif_msg_drv(pegasus)) |
272 | dev_err(&pegasus->intf->dev, "%s, status %d\n", | 278 | dev_err(&pegasus->intf->dev, "%s, status %d\n", |
273 | __FUNCTION__, ret); | 279 | __FUNCTION__, ret); |
@@ -298,10 +304,13 @@ static int update_eth_regs_async(pegasus_t * pegasus) | |||
298 | (char *) &pegasus->dr, | 304 | (char *) &pegasus->dr, |
299 | pegasus->eth_regs, 3, ctrl_callback, pegasus); | 305 | pegasus->eth_regs, 3, ctrl_callback, pegasus); |
300 | 306 | ||
301 | if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) | 307 | if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { |
308 | if (ret == -ENODEV) | ||
309 | netif_device_detach(pegasus->net); | ||
302 | if (netif_msg_drv(pegasus)) | 310 | if (netif_msg_drv(pegasus)) |
303 | dev_err(&pegasus->intf->dev, "%s, status %d\n", | 311 | dev_err(&pegasus->intf->dev, "%s, status %d\n", |
304 | __FUNCTION__, ret); | 312 | __FUNCTION__, ret); |
313 | } | ||
305 | 314 | ||
306 | return ret; | 315 | return ret; |
307 | } | 316 | } |
@@ -692,7 +701,10 @@ goon: | |||
692 | usb_rcvbulkpipe(pegasus->usb, 1), | 701 | usb_rcvbulkpipe(pegasus->usb, 1), |
693 | pegasus->rx_skb->data, PEGASUS_MTU + 8, | 702 | pegasus->rx_skb->data, PEGASUS_MTU + 8, |
694 | read_bulk_callback, pegasus); | 703 | read_bulk_callback, pegasus); |
695 | if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) { | 704 | rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); |
705 | if (rx_status == -ENODEV) | ||
706 | netif_device_detach(pegasus->net); | ||
707 | else if (rx_status) { | ||
696 | pegasus->flags |= PEGASUS_RX_URB_FAIL; | 708 | pegasus->flags |= PEGASUS_RX_URB_FAIL; |
697 | goto tl_sched; | 709 | goto tl_sched; |
698 | } else { | 710 | } else { |
@@ -709,6 +721,7 @@ static void rx_fixup(unsigned long data) | |||
709 | { | 721 | { |
710 | pegasus_t *pegasus; | 722 | pegasus_t *pegasus; |
711 | unsigned long flags; | 723 | unsigned long flags; |
724 | int status; | ||
712 | 725 | ||
713 | pegasus = (pegasus_t *) data; | 726 | pegasus = (pegasus_t *) data; |
714 | if (pegasus->flags & PEGASUS_UNPLUG) | 727 | if (pegasus->flags & PEGASUS_UNPLUG) |
@@ -734,7 +747,10 @@ static void rx_fixup(unsigned long data) | |||
734 | pegasus->rx_skb->data, PEGASUS_MTU + 8, | 747 | pegasus->rx_skb->data, PEGASUS_MTU + 8, |
735 | read_bulk_callback, pegasus); | 748 | read_bulk_callback, pegasus); |
736 | try_again: | 749 | try_again: |
737 | if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) { | 750 | status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); |
751 | if (status == -ENODEV) | ||
752 | netif_device_detach(pegasus->net); | ||
753 | else if (status) { | ||
738 | pegasus->flags |= PEGASUS_RX_URB_FAIL; | 754 | pegasus->flags |= PEGASUS_RX_URB_FAIL; |
739 | tasklet_schedule(&pegasus->rx_tl); | 755 | tasklet_schedule(&pegasus->rx_tl); |
740 | } else { | 756 | } else { |
@@ -836,6 +852,8 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) | |||
836 | } | 852 | } |
837 | 853 | ||
838 | status = usb_submit_urb(urb, SLAB_ATOMIC); | 854 | status = usb_submit_urb(urb, SLAB_ATOMIC); |
855 | if (status == -ENODEV) | ||
856 | netif_device_detach(pegasus->net); | ||
839 | if (status && netif_msg_timer(pegasus)) | 857 | if (status && netif_msg_timer(pegasus)) |
840 | printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n", | 858 | printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n", |
841 | net->name, status); | 859 | net->name, status); |
@@ -874,6 +892,7 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) | |||
874 | /* cleanup should already have been scheduled */ | 892 | /* cleanup should already have been scheduled */ |
875 | break; | 893 | break; |
876 | case -ENODEV: /* disconnect() upcoming */ | 894 | case -ENODEV: /* disconnect() upcoming */ |
895 | netif_device_detach(pegasus->net); | ||
877 | break; | 896 | break; |
878 | default: | 897 | default: |
879 | pegasus->stats.tx_errors++; | 898 | pegasus->stats.tx_errors++; |
@@ -999,6 +1018,8 @@ static int pegasus_open(struct net_device *net) | |||
999 | pegasus->rx_skb->data, PEGASUS_MTU + 8, | 1018 | pegasus->rx_skb->data, PEGASUS_MTU + 8, |
1000 | read_bulk_callback, pegasus); | 1019 | read_bulk_callback, pegasus); |
1001 | if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { | 1020 | if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { |
1021 | if (res == -ENODEV) | ||
1022 | netif_device_detach(pegasus->net); | ||
1002 | if (netif_msg_ifup(pegasus)) | 1023 | if (netif_msg_ifup(pegasus)) |
1003 | pr_debug("%s: failed rx_urb, %d", net->name, res); | 1024 | pr_debug("%s: failed rx_urb, %d", net->name, res); |
1004 | goto exit; | 1025 | goto exit; |
@@ -1009,6 +1030,8 @@ static int pegasus_open(struct net_device *net) | |||
1009 | pegasus->intr_buff, sizeof (pegasus->intr_buff), | 1030 | pegasus->intr_buff, sizeof (pegasus->intr_buff), |
1010 | intr_callback, pegasus, pegasus->intr_interval); | 1031 | intr_callback, pegasus, pegasus->intr_interval); |
1011 | if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) { | 1032 | if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) { |
1033 | if (res == -ENODEV) | ||
1034 | netif_device_detach(pegasus->net); | ||
1012 | if (netif_msg_ifup(pegasus)) | 1035 | if (netif_msg_ifup(pegasus)) |
1013 | pr_debug("%s: failed intr_urb, %d\n", net->name, res); | 1036 | pr_debug("%s: failed intr_urb, %d\n", net->name, res); |
1014 | usb_kill_urb(pegasus->rx_urb); | 1037 | usb_kill_urb(pegasus->rx_urb); |
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c index 94ddfe16fdda..f551546d7521 100644 --- a/drivers/usb/net/rndis_host.c +++ b/drivers/usb/net/rndis_host.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
31 | #include <linux/mii.h> | 31 | #include <linux/mii.h> |
32 | #include <linux/usb.h> | 32 | #include <linux/usb.h> |
33 | #include <linux/usb_cdc.h> | 33 | #include <linux/usb/cdc.h> |
34 | 34 | ||
35 | #include "usbnet.h" | 35 | #include "usbnet.h" |
36 | 36 | ||
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c index f7ac9d6b9856..813e470d0600 100644 --- a/drivers/usb/net/zaurus.c +++ b/drivers/usb/net/zaurus.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/mii.h> | 30 | #include <linux/mii.h> |
31 | #include <linux/crc32.h> | 31 | #include <linux/crc32.h> |
32 | #include <linux/usb.h> | 32 | #include <linux/usb.h> |
33 | #include <linux/usb_cdc.h> | 33 | #include <linux/usb/cdc.h> |
34 | 34 | ||
35 | #include "usbnet.h" | 35 | #include "usbnet.h" |
36 | 36 | ||
@@ -109,7 +109,7 @@ static const struct driver_info zaurus_sl5x00_info = { | |||
109 | .check_connect = always_connected, | 109 | .check_connect = always_connected, |
110 | .bind = zaurus_bind, | 110 | .bind = zaurus_bind, |
111 | .unbind = usbnet_cdc_unbind, | 111 | .unbind = usbnet_cdc_unbind, |
112 | .tx_fixup = zaurus_tx_fixup, | 112 | .tx_fixup = zaurus_tx_fixup, |
113 | }; | 113 | }; |
114 | #define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info) | 114 | #define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info) |
115 | 115 | ||
@@ -119,7 +119,7 @@ static const struct driver_info zaurus_pxa_info = { | |||
119 | .check_connect = always_connected, | 119 | .check_connect = always_connected, |
120 | .bind = zaurus_bind, | 120 | .bind = zaurus_bind, |
121 | .unbind = usbnet_cdc_unbind, | 121 | .unbind = usbnet_cdc_unbind, |
122 | .tx_fixup = zaurus_tx_fixup, | 122 | .tx_fixup = zaurus_tx_fixup, |
123 | }; | 123 | }; |
124 | #define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info) | 124 | #define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info) |
125 | 125 | ||
@@ -129,7 +129,7 @@ static const struct driver_info olympus_mxl_info = { | |||
129 | .check_connect = always_connected, | 129 | .check_connect = always_connected, |
130 | .bind = zaurus_bind, | 130 | .bind = zaurus_bind, |
131 | .unbind = usbnet_cdc_unbind, | 131 | .unbind = usbnet_cdc_unbind, |
132 | .tx_fixup = zaurus_tx_fixup, | 132 | .tx_fixup = zaurus_tx_fixup, |
133 | }; | 133 | }; |
134 | #define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info) | 134 | #define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info) |
135 | 135 | ||
@@ -228,6 +228,11 @@ bad_detail: | |||
228 | detail->bDetailData[2]); | 228 | detail->bDetailData[2]); |
229 | goto bad_desc; | 229 | goto bad_desc; |
230 | } | 230 | } |
231 | |||
232 | /* same extra framing as for non-BLAN mode */ | ||
233 | dev->net->hard_header_len += 6; | ||
234 | dev->rx_urb_size = dev->net->hard_header_len | ||
235 | + dev->net->mtu; | ||
231 | break; | 236 | break; |
232 | } | 237 | } |
233 | next_desc: | 238 | next_desc: |
@@ -258,7 +263,7 @@ static const struct driver_info bogus_mdlm_info = { | |||
258 | .description = "pseudo-MDLM (BLAN) device", | 263 | .description = "pseudo-MDLM (BLAN) device", |
259 | .flags = FLAG_FRAMING_Z, | 264 | .flags = FLAG_FRAMING_Z, |
260 | .check_connect = always_connected, | 265 | .check_connect = always_connected, |
261 | .tx_fixup = zaurus_tx_fixup, | 266 | .tx_fixup = zaurus_tx_fixup, |
262 | .bind = blan_mdlm_bind, | 267 | .bind = blan_mdlm_bind, |
263 | }; | 268 | }; |
264 | 269 | ||
@@ -367,13 +372,13 @@ static struct usb_driver zaurus_driver = { | |||
367 | 372 | ||
368 | static int __init zaurus_init(void) | 373 | static int __init zaurus_init(void) |
369 | { | 374 | { |
370 | return usb_register(&zaurus_driver); | 375 | return usb_register(&zaurus_driver); |
371 | } | 376 | } |
372 | module_init(zaurus_init); | 377 | module_init(zaurus_init); |
373 | 378 | ||
374 | static void __exit zaurus_exit(void) | 379 | static void __exit zaurus_exit(void) |
375 | { | 380 | { |
376 | usb_deregister(&zaurus_driver); | 381 | usb_deregister(&zaurus_driver); |
377 | } | 382 | } |
378 | module_exit(zaurus_exit); | 383 | module_exit(zaurus_exit); |
379 | 384 | ||
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c deleted file mode 100644 index 9b1e4ed1d07e..000000000000 --- a/drivers/usb/net/zd1201.c +++ /dev/null | |||
@@ -1,1944 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for ZyDAS zd1201 based wireless USB devices. | ||
3 | * | ||
4 | * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * Parts of this driver have been derived from a wlan-ng version | ||
11 | * modified by ZyDAS. They also made documentation available, thanks! | ||
12 | * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/usb.h> | ||
17 | #include <linux/netdevice.h> | ||
18 | #include <linux/etherdevice.h> | ||
19 | #include <linux/wireless.h> | ||
20 | #include <net/iw_handler.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/if_arp.h> | ||
23 | #include <linux/firmware.h> | ||
24 | #include <net/ieee80211.h> | ||
25 | #include "zd1201.h" | ||
26 | |||
27 | static struct usb_device_id zd1201_table[] = { | ||
28 | {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */ | ||
29 | {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ | ||
30 | {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ | ||
31 | {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ | ||
32 | {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ | ||
33 | {} | ||
34 | }; | ||
35 | |||
36 | static int ap = 0; /* Are we an AP or a normal station? */ | ||
37 | |||
38 | #define ZD1201_VERSION "0.15" | ||
39 | |||
40 | MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>"); | ||
41 | MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters"); | ||
42 | MODULE_VERSION(ZD1201_VERSION); | ||
43 | MODULE_LICENSE("GPL"); | ||
44 | module_param(ap, int, 0); | ||
45 | MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded"); | ||
46 | MODULE_DEVICE_TABLE(usb, zd1201_table); | ||
47 | |||
48 | |||
49 | static int zd1201_fw_upload(struct usb_device *dev, int apfw) | ||
50 | { | ||
51 | const struct firmware *fw_entry; | ||
52 | char* data; | ||
53 | unsigned long len; | ||
54 | int err; | ||
55 | unsigned char ret; | ||
56 | char *buf; | ||
57 | char *fwfile; | ||
58 | |||
59 | if (apfw) | ||
60 | fwfile = "zd1201-ap.fw"; | ||
61 | else | ||
62 | fwfile = "zd1201.fw"; | ||
63 | |||
64 | err = request_firmware(&fw_entry, fwfile, &dev->dev); | ||
65 | if (err) { | ||
66 | dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile); | ||
67 | dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n"); | ||
68 | dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info\n"); | ||
69 | return err; | ||
70 | } | ||
71 | |||
72 | data = fw_entry->data; | ||
73 | len = fw_entry->size; | ||
74 | |||
75 | buf = kmalloc(1024, GFP_ATOMIC); | ||
76 | if (!buf) | ||
77 | goto exit; | ||
78 | |||
79 | while (len > 0) { | ||
80 | int translen = (len > 1024) ? 1024 : len; | ||
81 | memcpy(buf, data, translen); | ||
82 | |||
83 | err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, | ||
84 | USB_DIR_OUT | 0x40, 0, 0, buf, translen, | ||
85 | ZD1201_FW_TIMEOUT); | ||
86 | if (err < 0) | ||
87 | goto exit; | ||
88 | |||
89 | len -= translen; | ||
90 | data += translen; | ||
91 | } | ||
92 | |||
93 | err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2, | ||
94 | USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT); | ||
95 | if (err < 0) | ||
96 | goto exit; | ||
97 | |||
98 | err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4, | ||
99 | USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT); | ||
100 | if (err < 0) | ||
101 | goto exit; | ||
102 | |||
103 | if (ret & 0x80) { | ||
104 | err = -EIO; | ||
105 | goto exit; | ||
106 | } | ||
107 | |||
108 | err = 0; | ||
109 | exit: | ||
110 | kfree(buf); | ||
111 | release_firmware(fw_entry); | ||
112 | return err; | ||
113 | } | ||
114 | |||
115 | static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs) | ||
116 | { | ||
117 | struct zd1201 *zd = urb->context; | ||
118 | |||
119 | switch(urb->status) { | ||
120 | case -EILSEQ: | ||
121 | case -ENODEV: | ||
122 | case -ETIMEDOUT: | ||
123 | case -ENOENT: | ||
124 | case -EPIPE: | ||
125 | case -EOVERFLOW: | ||
126 | case -ESHUTDOWN: | ||
127 | dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", | ||
128 | zd->dev->name, urb->status); | ||
129 | } | ||
130 | |||
131 | kfree(urb->transfer_buffer); | ||
132 | usb_free_urb(urb); | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | /* cmdreq message: | ||
137 | u32 type | ||
138 | u16 cmd | ||
139 | u16 parm0 | ||
140 | u16 parm1 | ||
141 | u16 parm2 | ||
142 | u8 pad[4] | ||
143 | |||
144 | total: 4 + 2 + 2 + 2 + 2 + 4 = 16 | ||
145 | */ | ||
146 | static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, | ||
147 | int parm1, int parm2) | ||
148 | { | ||
149 | unsigned char *command; | ||
150 | int ret; | ||
151 | struct urb *urb; | ||
152 | |||
153 | command = kmalloc(16, GFP_ATOMIC); | ||
154 | if (!command) | ||
155 | return -ENOMEM; | ||
156 | |||
157 | *((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ); | ||
158 | *((__le16*)&command[4]) = cpu_to_le16(cmd); | ||
159 | *((__le16*)&command[6]) = cpu_to_le16(parm0); | ||
160 | *((__le16*)&command[8]) = cpu_to_le16(parm1); | ||
161 | *((__le16*)&command[10])= cpu_to_le16(parm2); | ||
162 | |||
163 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
164 | if (!urb) { | ||
165 | kfree(command); | ||
166 | return -ENOMEM; | ||
167 | } | ||
168 | usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), | ||
169 | command, 16, zd1201_usbfree, zd); | ||
170 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
171 | if (ret) { | ||
172 | kfree(command); | ||
173 | usb_free_urb(urb); | ||
174 | } | ||
175 | |||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | /* Callback after sending out a packet */ | ||
180 | static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs) | ||
181 | { | ||
182 | struct zd1201 *zd = urb->context; | ||
183 | netif_wake_queue(zd->dev); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | /* Incoming data */ | ||
188 | static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) | ||
189 | { | ||
190 | struct zd1201 *zd = urb->context; | ||
191 | int free = 0; | ||
192 | unsigned char *data = urb->transfer_buffer; | ||
193 | struct sk_buff *skb; | ||
194 | unsigned char type; | ||
195 | |||
196 | if (!zd) { | ||
197 | free = 1; | ||
198 | goto exit; | ||
199 | } | ||
200 | |||
201 | switch(urb->status) { | ||
202 | case -EILSEQ: | ||
203 | case -ENODEV: | ||
204 | case -ETIMEDOUT: | ||
205 | case -ENOENT: | ||
206 | case -EPIPE: | ||
207 | case -EOVERFLOW: | ||
208 | case -ESHUTDOWN: | ||
209 | dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n", | ||
210 | zd->dev->name, urb->status); | ||
211 | free = 1; | ||
212 | goto exit; | ||
213 | } | ||
214 | |||
215 | if (urb->status != 0 || urb->actual_length == 0) | ||
216 | goto resubmit; | ||
217 | |||
218 | type = data[0]; | ||
219 | if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) { | ||
220 | memcpy(zd->rxdata, data, urb->actual_length); | ||
221 | zd->rxlen = urb->actual_length; | ||
222 | zd->rxdatas = 1; | ||
223 | wake_up(&zd->rxdataq); | ||
224 | } | ||
225 | /* Info frame */ | ||
226 | if (type == ZD1201_PACKET_INQUIRE) { | ||
227 | int i = 0; | ||
228 | unsigned short infotype, framelen, copylen; | ||
229 | framelen = le16_to_cpu(*(__le16*)&data[4]); | ||
230 | infotype = le16_to_cpu(*(__le16*)&data[6]); | ||
231 | |||
232 | if (infotype == ZD1201_INF_LINKSTATUS) { | ||
233 | short linkstatus; | ||
234 | |||
235 | linkstatus = le16_to_cpu(*(__le16*)&data[8]); | ||
236 | switch(linkstatus) { | ||
237 | case 1: | ||
238 | netif_carrier_on(zd->dev); | ||
239 | break; | ||
240 | case 2: | ||
241 | netif_carrier_off(zd->dev); | ||
242 | break; | ||
243 | case 3: | ||
244 | netif_carrier_off(zd->dev); | ||
245 | break; | ||
246 | case 4: | ||
247 | netif_carrier_on(zd->dev); | ||
248 | break; | ||
249 | default: | ||
250 | netif_carrier_off(zd->dev); | ||
251 | } | ||
252 | goto resubmit; | ||
253 | } | ||
254 | if (infotype == ZD1201_INF_ASSOCSTATUS) { | ||
255 | short status = le16_to_cpu(*(__le16*)(data+8)); | ||
256 | int event; | ||
257 | union iwreq_data wrqu; | ||
258 | |||
259 | switch (status) { | ||
260 | case ZD1201_ASSOCSTATUS_STAASSOC: | ||
261 | case ZD1201_ASSOCSTATUS_REASSOC: | ||
262 | event = IWEVREGISTERED; | ||
263 | break; | ||
264 | case ZD1201_ASSOCSTATUS_DISASSOC: | ||
265 | case ZD1201_ASSOCSTATUS_ASSOCFAIL: | ||
266 | case ZD1201_ASSOCSTATUS_AUTHFAIL: | ||
267 | default: | ||
268 | event = IWEVEXPIRED; | ||
269 | } | ||
270 | memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN); | ||
271 | wrqu.addr.sa_family = ARPHRD_ETHER; | ||
272 | |||
273 | /* Send event to user space */ | ||
274 | wireless_send_event(zd->dev, event, &wrqu, NULL); | ||
275 | |||
276 | goto resubmit; | ||
277 | } | ||
278 | if (infotype == ZD1201_INF_AUTHREQ) { | ||
279 | union iwreq_data wrqu; | ||
280 | |||
281 | memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN); | ||
282 | wrqu.addr.sa_family = ARPHRD_ETHER; | ||
283 | /* There isn't a event that trully fits this request. | ||
284 | We assume that userspace will be smart enough to | ||
285 | see a new station being expired and sends back a | ||
286 | authstation ioctl to authorize it. */ | ||
287 | wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL); | ||
288 | goto resubmit; | ||
289 | } | ||
290 | /* Other infotypes are handled outside this handler */ | ||
291 | zd->rxlen = 0; | ||
292 | while (i < urb->actual_length) { | ||
293 | copylen = le16_to_cpu(*(__le16*)&data[i+2]); | ||
294 | /* Sanity check, sometimes we get junk */ | ||
295 | if (copylen+zd->rxlen > sizeof(zd->rxdata)) | ||
296 | break; | ||
297 | memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen); | ||
298 | zd->rxlen += copylen; | ||
299 | i += 64; | ||
300 | } | ||
301 | if (i >= urb->actual_length) { | ||
302 | zd->rxdatas = 1; | ||
303 | wake_up(&zd->rxdataq); | ||
304 | } | ||
305 | goto resubmit; | ||
306 | } | ||
307 | /* Actual data */ | ||
308 | if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) { | ||
309 | int datalen = urb->actual_length-1; | ||
310 | unsigned short len, fc, seq; | ||
311 | struct hlist_node *node; | ||
312 | |||
313 | len = ntohs(*(__be16 *)&data[datalen-2]); | ||
314 | if (len>datalen) | ||
315 | len=datalen; | ||
316 | fc = le16_to_cpu(*(__le16 *)&data[datalen-16]); | ||
317 | seq = le16_to_cpu(*(__le16 *)&data[datalen-24]); | ||
318 | |||
319 | if(zd->monitor) { | ||
320 | if (datalen < 24) | ||
321 | goto resubmit; | ||
322 | if (!(skb = dev_alloc_skb(datalen+24))) | ||
323 | goto resubmit; | ||
324 | |||
325 | memcpy(skb_put(skb, 2), &data[datalen-16], 2); | ||
326 | memcpy(skb_put(skb, 2), &data[datalen-2], 2); | ||
327 | memcpy(skb_put(skb, 6), &data[datalen-14], 6); | ||
328 | memcpy(skb_put(skb, 6), &data[datalen-22], 6); | ||
329 | memcpy(skb_put(skb, 6), &data[datalen-8], 6); | ||
330 | memcpy(skb_put(skb, 2), &data[datalen-24], 2); | ||
331 | memcpy(skb_put(skb, len), data, len); | ||
332 | skb->dev = zd->dev; | ||
333 | skb->dev->last_rx = jiffies; | ||
334 | skb->protocol = eth_type_trans(skb, zd->dev); | ||
335 | zd->stats.rx_packets++; | ||
336 | zd->stats.rx_bytes += skb->len; | ||
337 | netif_rx(skb); | ||
338 | goto resubmit; | ||
339 | } | ||
340 | |||
341 | if ((seq & IEEE80211_SCTL_FRAG) || | ||
342 | (fc & IEEE80211_FCTL_MOREFRAGS)) { | ||
343 | struct zd1201_frag *frag = NULL; | ||
344 | char *ptr; | ||
345 | |||
346 | if (datalen<14) | ||
347 | goto resubmit; | ||
348 | if ((seq & IEEE80211_SCTL_FRAG) == 0) { | ||
349 | frag = kmalloc(sizeof(*frag), GFP_ATOMIC); | ||
350 | if (!frag) | ||
351 | goto resubmit; | ||
352 | skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2); | ||
353 | if (!skb) { | ||
354 | kfree(frag); | ||
355 | goto resubmit; | ||
356 | } | ||
357 | frag->skb = skb; | ||
358 | frag->seq = seq & IEEE80211_SCTL_SEQ; | ||
359 | skb_reserve(skb, 2); | ||
360 | memcpy(skb_put(skb, 12), &data[datalen-14], 12); | ||
361 | memcpy(skb_put(skb, 2), &data[6], 2); | ||
362 | memcpy(skb_put(skb, len), data+8, len); | ||
363 | hlist_add_head(&frag->fnode, &zd->fraglist); | ||
364 | goto resubmit; | ||
365 | } | ||
366 | hlist_for_each_entry(frag, node, &zd->fraglist, fnode) | ||
367 | if(frag->seq == (seq&IEEE80211_SCTL_SEQ)) | ||
368 | break; | ||
369 | if (!frag) | ||
370 | goto resubmit; | ||
371 | skb = frag->skb; | ||
372 | ptr = skb_put(skb, len); | ||
373 | if (ptr) | ||
374 | memcpy(ptr, data+8, len); | ||
375 | if (fc & IEEE80211_FCTL_MOREFRAGS) | ||
376 | goto resubmit; | ||
377 | hlist_del_init(&frag->fnode); | ||
378 | kfree(frag); | ||
379 | /* Fallthrough */ | ||
380 | } else { | ||
381 | if (datalen<14) | ||
382 | goto resubmit; | ||
383 | skb = dev_alloc_skb(len + 14 + 2); | ||
384 | if (!skb) | ||
385 | goto resubmit; | ||
386 | skb_reserve(skb, 2); | ||
387 | memcpy(skb_put(skb, 12), &data[datalen-14], 12); | ||
388 | memcpy(skb_put(skb, 2), &data[6], 2); | ||
389 | memcpy(skb_put(skb, len), data+8, len); | ||
390 | } | ||
391 | skb->dev = zd->dev; | ||
392 | skb->dev->last_rx = jiffies; | ||
393 | skb->protocol = eth_type_trans(skb, zd->dev); | ||
394 | zd->stats.rx_packets++; | ||
395 | zd->stats.rx_bytes += skb->len; | ||
396 | netif_rx(skb); | ||
397 | } | ||
398 | resubmit: | ||
399 | memset(data, 0, ZD1201_RXSIZE); | ||
400 | |||
401 | urb->status = 0; | ||
402 | urb->dev = zd->usb; | ||
403 | if(usb_submit_urb(urb, GFP_ATOMIC)) | ||
404 | free = 1; | ||
405 | |||
406 | exit: | ||
407 | if (free) { | ||
408 | zd->rxlen = 0; | ||
409 | zd->rxdatas = 1; | ||
410 | wake_up(&zd->rxdataq); | ||
411 | kfree(urb->transfer_buffer); | ||
412 | } | ||
413 | return; | ||
414 | } | ||
415 | |||
416 | static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, | ||
417 | unsigned int riddatalen) | ||
418 | { | ||
419 | int err; | ||
420 | int i = 0; | ||
421 | int code; | ||
422 | int rid_fid; | ||
423 | int length; | ||
424 | unsigned char *pdata; | ||
425 | |||
426 | zd->rxdatas = 0; | ||
427 | err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0); | ||
428 | if (err) | ||
429 | return err; | ||
430 | |||
431 | wait_event_interruptible(zd->rxdataq, zd->rxdatas); | ||
432 | if (!zd->rxlen) | ||
433 | return -EIO; | ||
434 | |||
435 | code = le16_to_cpu(*(__le16*)(&zd->rxdata[4])); | ||
436 | rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6])); | ||
437 | length = le16_to_cpu(*(__le16*)(&zd->rxdata[8])); | ||
438 | if (length > zd->rxlen) | ||
439 | length = zd->rxlen-6; | ||
440 | |||
441 | /* If access bit is not on, then error */ | ||
442 | if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid ) | ||
443 | return -EINVAL; | ||
444 | |||
445 | /* Not enough buffer for allocating data */ | ||
446 | if (riddatalen != (length - 4)) { | ||
447 | dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n", | ||
448 | riddatalen, zd->rxlen, length, rid, rid_fid); | ||
449 | return -ENODATA; | ||
450 | } | ||
451 | |||
452 | zd->rxdatas = 0; | ||
453 | /* Issue SetRxRid commnd */ | ||
454 | err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length); | ||
455 | if (err) | ||
456 | return err; | ||
457 | |||
458 | /* Receive RID record from resource packets */ | ||
459 | wait_event_interruptible(zd->rxdataq, zd->rxdatas); | ||
460 | if (!zd->rxlen) | ||
461 | return -EIO; | ||
462 | |||
463 | if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) { | ||
464 | dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n", | ||
465 | zd->rxdata[zd->rxlen-1]); | ||
466 | return -EINVAL; | ||
467 | } | ||
468 | |||
469 | /* Set the data pointer and received data length */ | ||
470 | pdata = zd->rxdata; | ||
471 | length = zd->rxlen; | ||
472 | |||
473 | do { | ||
474 | int actual_length; | ||
475 | |||
476 | actual_length = (length > 64) ? 64 : length; | ||
477 | |||
478 | if(pdata[0] != 0x3) { | ||
479 | dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n", | ||
480 | pdata[0]); | ||
481 | return -EINVAL; | ||
482 | } | ||
483 | |||
484 | if (actual_length != 64) { | ||
485 | /* Trim the last packet type byte */ | ||
486 | actual_length--; | ||
487 | } | ||
488 | |||
489 | /* Skip the 4 bytes header (RID length and RID) */ | ||
490 | if(i == 0) { | ||
491 | pdata += 8; | ||
492 | actual_length -= 8; | ||
493 | } | ||
494 | else { | ||
495 | pdata += 4; | ||
496 | actual_length -= 4; | ||
497 | } | ||
498 | |||
499 | memcpy(riddata, pdata, actual_length); | ||
500 | riddata += actual_length; | ||
501 | pdata += actual_length; | ||
502 | length -= 64; | ||
503 | i++; | ||
504 | } while (length > 0); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | /* | ||
510 | * resreq: | ||
511 | * byte type | ||
512 | * byte sequence | ||
513 | * u16 reserved | ||
514 | * byte data[12] | ||
515 | * total: 16 | ||
516 | */ | ||
517 | static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait) | ||
518 | { | ||
519 | int err; | ||
520 | unsigned char *request; | ||
521 | int reqlen; | ||
522 | char seq=0; | ||
523 | struct urb *urb; | ||
524 | gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC; | ||
525 | |||
526 | len += 4; /* first 4 are for header */ | ||
527 | |||
528 | zd->rxdatas = 0; | ||
529 | zd->rxlen = 0; | ||
530 | for (seq=0; len > 0; seq++) { | ||
531 | request = kmalloc(16, gfp_mask); | ||
532 | if (!request) | ||
533 | return -ENOMEM; | ||
534 | urb = usb_alloc_urb(0, gfp_mask); | ||
535 | if (!urb) { | ||
536 | kfree(request); | ||
537 | return -ENOMEM; | ||
538 | } | ||
539 | memset(request, 0, 16); | ||
540 | reqlen = len>12 ? 12 : len; | ||
541 | request[0] = ZD1201_USB_RESREQ; | ||
542 | request[1] = seq; | ||
543 | request[2] = 0; | ||
544 | request[3] = 0; | ||
545 | if (request[1] == 0) { | ||
546 | /* add header */ | ||
547 | *(__le16*)&request[4] = cpu_to_le16((len-2+1)/2); | ||
548 | *(__le16*)&request[6] = cpu_to_le16(rid); | ||
549 | memcpy(request+8, buf, reqlen-4); | ||
550 | buf += reqlen-4; | ||
551 | } else { | ||
552 | memcpy(request+4, buf, reqlen); | ||
553 | buf += reqlen; | ||
554 | } | ||
555 | |||
556 | len -= reqlen; | ||
557 | |||
558 | usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, | ||
559 | zd->endp_out2), request, 16, zd1201_usbfree, zd); | ||
560 | err = usb_submit_urb(urb, gfp_mask); | ||
561 | if (err) | ||
562 | goto err; | ||
563 | } | ||
564 | |||
565 | request = kmalloc(16, gfp_mask); | ||
566 | if (!request) | ||
567 | return -ENOMEM; | ||
568 | urb = usb_alloc_urb(0, gfp_mask); | ||
569 | if (!urb) { | ||
570 | kfree(request); | ||
571 | return -ENOMEM; | ||
572 | } | ||
573 | *((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ); | ||
574 | *((__le16*)&request[4]) = | ||
575 | cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT); | ||
576 | *((__le16*)&request[6]) = cpu_to_le16(rid); | ||
577 | *((__le16*)&request[8]) = cpu_to_le16(0); | ||
578 | *((__le16*)&request[10]) = cpu_to_le16(0); | ||
579 | usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), | ||
580 | request, 16, zd1201_usbfree, zd); | ||
581 | err = usb_submit_urb(urb, gfp_mask); | ||
582 | if (err) | ||
583 | goto err; | ||
584 | |||
585 | if (wait) { | ||
586 | wait_event_interruptible(zd->rxdataq, zd->rxdatas); | ||
587 | if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) { | ||
588 | dev_dbg(&zd->usb->dev, "wrong or no RID received\n"); | ||
589 | } | ||
590 | } | ||
591 | |||
592 | return 0; | ||
593 | err: | ||
594 | kfree(request); | ||
595 | usb_free_urb(urb); | ||
596 | return err; | ||
597 | } | ||
598 | |||
599 | static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val) | ||
600 | { | ||
601 | int err; | ||
602 | __le16 zdval; | ||
603 | |||
604 | err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16)); | ||
605 | if (err) | ||
606 | return err; | ||
607 | *val = le16_to_cpu(zdval); | ||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val) | ||
612 | { | ||
613 | __le16 zdval = cpu_to_le16(val); | ||
614 | return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1)); | ||
615 | } | ||
616 | |||
617 | static int zd1201_drvr_start(struct zd1201 *zd) | ||
618 | { | ||
619 | int err, i; | ||
620 | short max; | ||
621 | __le16 zdmax; | ||
622 | unsigned char *buffer; | ||
623 | |||
624 | buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL); | ||
625 | if (!buffer) | ||
626 | return -ENOMEM; | ||
627 | |||
628 | usb_fill_bulk_urb(zd->rx_urb, zd->usb, | ||
629 | usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE, | ||
630 | zd1201_usbrx, zd); | ||
631 | |||
632 | err = usb_submit_urb(zd->rx_urb, GFP_KERNEL); | ||
633 | if (err) | ||
634 | goto err_buffer; | ||
635 | |||
636 | err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); | ||
637 | if (err) | ||
638 | goto err_urb; | ||
639 | |||
640 | err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax, | ||
641 | sizeof(__le16)); | ||
642 | if (err) | ||
643 | goto err_urb; | ||
644 | |||
645 | max = le16_to_cpu(zdmax); | ||
646 | for (i=0; i<max; i++) { | ||
647 | err = zd1201_docmd(zd, ZD1201_CMDCODE_ALLOC, 1514, 0, 0); | ||
648 | if (err) | ||
649 | goto err_urb; | ||
650 | } | ||
651 | |||
652 | return 0; | ||
653 | |||
654 | err_urb: | ||
655 | usb_kill_urb(zd->rx_urb); | ||
656 | return err; | ||
657 | err_buffer: | ||
658 | kfree(buffer); | ||
659 | return err; | ||
660 | } | ||
661 | |||
662 | /* Magic alert: The firmware doesn't seem to like the MAC state being | ||
663 | * toggled in promisc (aka monitor) mode. | ||
664 | * (It works a number of times, but will halt eventually) | ||
665 | * So we turn it of before disabling and on after enabling if needed. | ||
666 | */ | ||
667 | static int zd1201_enable(struct zd1201 *zd) | ||
668 | { | ||
669 | int err; | ||
670 | |||
671 | if (zd->mac_enabled) | ||
672 | return 0; | ||
673 | |||
674 | err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0); | ||
675 | if (!err) | ||
676 | zd->mac_enabled = 1; | ||
677 | |||
678 | if (zd->monitor) | ||
679 | err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1); | ||
680 | |||
681 | return err; | ||
682 | } | ||
683 | |||
684 | static int zd1201_disable(struct zd1201 *zd) | ||
685 | { | ||
686 | int err; | ||
687 | |||
688 | if (!zd->mac_enabled) | ||
689 | return 0; | ||
690 | if (zd->monitor) { | ||
691 | err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); | ||
692 | if (err) | ||
693 | return err; | ||
694 | } | ||
695 | |||
696 | err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0); | ||
697 | if (!err) | ||
698 | zd->mac_enabled = 0; | ||
699 | return err; | ||
700 | } | ||
701 | |||
702 | static int zd1201_mac_reset(struct zd1201 *zd) | ||
703 | { | ||
704 | if (!zd->mac_enabled) | ||
705 | return 0; | ||
706 | zd1201_disable(zd); | ||
707 | return zd1201_enable(zd); | ||
708 | } | ||
709 | |||
710 | static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen) | ||
711 | { | ||
712 | int err, val; | ||
713 | char buf[IW_ESSID_MAX_SIZE+2]; | ||
714 | |||
715 | err = zd1201_disable(zd); | ||
716 | if (err) | ||
717 | return err; | ||
718 | |||
719 | val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; | ||
720 | val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY; | ||
721 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val); | ||
722 | if (err) | ||
723 | return err; | ||
724 | |||
725 | *(__le16 *)buf = cpu_to_le16(essidlen); | ||
726 | memcpy(buf+2, essid, essidlen); | ||
727 | if (!zd->ap) { /* Normal station */ | ||
728 | err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, | ||
729 | IW_ESSID_MAX_SIZE+2, 1); | ||
730 | if (err) | ||
731 | return err; | ||
732 | } else { /* AP */ | ||
733 | err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf, | ||
734 | IW_ESSID_MAX_SIZE+2, 1); | ||
735 | if (err) | ||
736 | return err; | ||
737 | } | ||
738 | |||
739 | err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, | ||
740 | zd->dev->dev_addr, zd->dev->addr_len, 1); | ||
741 | if (err) | ||
742 | return err; | ||
743 | |||
744 | err = zd1201_enable(zd); | ||
745 | if (err) | ||
746 | return err; | ||
747 | |||
748 | msleep(100); | ||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | static int zd1201_net_open(struct net_device *dev) | ||
753 | { | ||
754 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
755 | |||
756 | /* Start MAC with wildcard if no essid set */ | ||
757 | if (!zd->mac_enabled) | ||
758 | zd1201_join(zd, zd->essid, zd->essidlen); | ||
759 | netif_start_queue(dev); | ||
760 | |||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | static int zd1201_net_stop(struct net_device *dev) | ||
765 | { | ||
766 | netif_stop_queue(dev); | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | /* | ||
772 | RFC 1042 encapsulates Ethernet frames in 802.11 frames | ||
773 | by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0 | ||
774 | (0x00, 0x00, 0x00). Zd requires an additional padding, copy | ||
775 | of ethernet addresses, length of the standard RFC 1042 packet | ||
776 | and a command byte (which is nul for tx). | ||
777 | |||
778 | tx frame (from Wlan NG): | ||
779 | RFC 1042: | ||
780 | llc 0xAA 0xAA 0x03 (802.2 LLC) | ||
781 | snap 0x00 0x00 0x00 (Ethernet encapsulated) | ||
782 | type 2 bytes, Ethernet type field | ||
783 | payload (minus eth header) | ||
784 | Zydas specific: | ||
785 | padding 1B if (skb->len+8+1)%64==0 | ||
786 | Eth MAC addr 12 bytes, Ethernet MAC addresses | ||
787 | length 2 bytes, RFC 1042 packet length | ||
788 | (llc+snap+type+payload) | ||
789 | zd 1 null byte, zd1201 packet type | ||
790 | */ | ||
791 | static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
792 | { | ||
793 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
794 | unsigned char *txbuf = zd->txdata; | ||
795 | int txbuflen, pad = 0, err; | ||
796 | struct urb *urb = zd->tx_urb; | ||
797 | |||
798 | if (!zd->mac_enabled || zd->monitor) { | ||
799 | zd->stats.tx_dropped++; | ||
800 | kfree_skb(skb); | ||
801 | return 0; | ||
802 | } | ||
803 | netif_stop_queue(dev); | ||
804 | |||
805 | txbuflen = skb->len + 8 + 1; | ||
806 | if (txbuflen%64 == 0) { | ||
807 | pad = 1; | ||
808 | txbuflen++; | ||
809 | } | ||
810 | txbuf[0] = 0xAA; | ||
811 | txbuf[1] = 0xAA; | ||
812 | txbuf[2] = 0x03; | ||
813 | txbuf[3] = 0x00; /* rfc1042 */ | ||
814 | txbuf[4] = 0x00; | ||
815 | txbuf[5] = 0x00; | ||
816 | |||
817 | memcpy(txbuf+6, skb->data+12, skb->len-12); | ||
818 | if (pad) | ||
819 | txbuf[skb->len-12+6]=0; | ||
820 | memcpy(txbuf+skb->len-12+6+pad, skb->data, 12); | ||
821 | *(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6); | ||
822 | txbuf[txbuflen-1] = 0; | ||
823 | |||
824 | usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out), | ||
825 | txbuf, txbuflen, zd1201_usbtx, zd); | ||
826 | |||
827 | err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC); | ||
828 | if (err) { | ||
829 | zd->stats.tx_errors++; | ||
830 | netif_start_queue(dev); | ||
831 | return err; | ||
832 | } | ||
833 | zd->stats.tx_packets++; | ||
834 | zd->stats.tx_bytes += skb->len; | ||
835 | dev->trans_start = jiffies; | ||
836 | kfree_skb(skb); | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | static void zd1201_tx_timeout(struct net_device *dev) | ||
842 | { | ||
843 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
844 | |||
845 | if (!zd) | ||
846 | return; | ||
847 | dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n", | ||
848 | dev->name); | ||
849 | usb_unlink_urb(zd->tx_urb); | ||
850 | zd->stats.tx_errors++; | ||
851 | /* Restart the timeout to quiet the watchdog: */ | ||
852 | dev->trans_start = jiffies; | ||
853 | } | ||
854 | |||
855 | static int zd1201_set_mac_address(struct net_device *dev, void *p) | ||
856 | { | ||
857 | struct sockaddr *addr = p; | ||
858 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
859 | int err; | ||
860 | |||
861 | if (!zd) | ||
862 | return -ENODEV; | ||
863 | |||
864 | err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, | ||
865 | addr->sa_data, dev->addr_len, 1); | ||
866 | if (err) | ||
867 | return err; | ||
868 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | ||
869 | |||
870 | return zd1201_mac_reset(zd); | ||
871 | } | ||
872 | |||
873 | static struct net_device_stats *zd1201_get_stats(struct net_device *dev) | ||
874 | { | ||
875 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
876 | |||
877 | return &zd->stats; | ||
878 | } | ||
879 | |||
880 | static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) | ||
881 | { | ||
882 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
883 | |||
884 | return &zd->iwstats; | ||
885 | } | ||
886 | |||
887 | static void zd1201_set_multicast(struct net_device *dev) | ||
888 | { | ||
889 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
890 | struct dev_mc_list *mc = dev->mc_list; | ||
891 | unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; | ||
892 | int i; | ||
893 | |||
894 | if (dev->mc_count > ZD1201_MAXMULTI) | ||
895 | return; | ||
896 | |||
897 | for (i=0; i<dev->mc_count; i++) { | ||
898 | memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN); | ||
899 | mc = mc->next; | ||
900 | } | ||
901 | zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, | ||
902 | dev->mc_count*ETH_ALEN, 0); | ||
903 | |||
904 | } | ||
905 | |||
906 | static int zd1201_config_commit(struct net_device *dev, | ||
907 | struct iw_request_info *info, struct iw_point *data, char *essid) | ||
908 | { | ||
909 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
910 | |||
911 | return zd1201_mac_reset(zd); | ||
912 | } | ||
913 | |||
914 | static int zd1201_get_name(struct net_device *dev, | ||
915 | struct iw_request_info *info, char *name, char *extra) | ||
916 | { | ||
917 | strcpy(name, "IEEE 802.11b"); | ||
918 | |||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | static int zd1201_set_freq(struct net_device *dev, | ||
923 | struct iw_request_info *info, struct iw_freq *freq, char *extra) | ||
924 | { | ||
925 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
926 | short channel = 0; | ||
927 | int err; | ||
928 | |||
929 | if (freq->e == 0) | ||
930 | channel = freq->m; | ||
931 | else { | ||
932 | if (freq->m >= 2482) | ||
933 | channel = 14; | ||
934 | if (freq->m >= 2407) | ||
935 | channel = (freq->m-2407)/5; | ||
936 | } | ||
937 | |||
938 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel); | ||
939 | if (err) | ||
940 | return err; | ||
941 | |||
942 | zd1201_mac_reset(zd); | ||
943 | |||
944 | return 0; | ||
945 | } | ||
946 | |||
947 | static int zd1201_get_freq(struct net_device *dev, | ||
948 | struct iw_request_info *info, struct iw_freq *freq, char *extra) | ||
949 | { | ||
950 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
951 | short channel; | ||
952 | int err; | ||
953 | |||
954 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel); | ||
955 | if (err) | ||
956 | return err; | ||
957 | freq->e = 0; | ||
958 | freq->m = channel; | ||
959 | |||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | static int zd1201_set_mode(struct net_device *dev, | ||
964 | struct iw_request_info *info, __u32 *mode, char *extra) | ||
965 | { | ||
966 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
967 | short porttype, monitor = 0; | ||
968 | unsigned char buffer[IW_ESSID_MAX_SIZE+2]; | ||
969 | int err; | ||
970 | |||
971 | if (zd->ap) { | ||
972 | if (*mode != IW_MODE_MASTER) | ||
973 | return -EINVAL; | ||
974 | return 0; | ||
975 | } | ||
976 | |||
977 | err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); | ||
978 | if (err) | ||
979 | return err; | ||
980 | zd->dev->type = ARPHRD_ETHER; | ||
981 | switch(*mode) { | ||
982 | case IW_MODE_MONITOR: | ||
983 | monitor = 1; | ||
984 | zd->dev->type = ARPHRD_IEEE80211; | ||
985 | /* Make sure we are no longer associated with by | ||
986 | setting an 'impossible' essid. | ||
987 | (otherwise we mess up firmware) | ||
988 | */ | ||
989 | zd1201_join(zd, "\0-*#\0", 5); | ||
990 | /* Put port in pIBSS */ | ||
991 | case 8: /* No pseudo-IBSS in wireless extensions (yet) */ | ||
992 | porttype = ZD1201_PORTTYPE_PSEUDOIBSS; | ||
993 | break; | ||
994 | case IW_MODE_ADHOC: | ||
995 | porttype = ZD1201_PORTTYPE_IBSS; | ||
996 | break; | ||
997 | case IW_MODE_INFRA: | ||
998 | porttype = ZD1201_PORTTYPE_BSS; | ||
999 | break; | ||
1000 | default: | ||
1001 | return -EINVAL; | ||
1002 | } | ||
1003 | |||
1004 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); | ||
1005 | if (err) | ||
1006 | return err; | ||
1007 | if (zd->monitor && !monitor) { | ||
1008 | zd1201_disable(zd); | ||
1009 | *(__le16 *)buffer = cpu_to_le16(zd->essidlen); | ||
1010 | memcpy(buffer+2, zd->essid, zd->essidlen); | ||
1011 | err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, | ||
1012 | buffer, IW_ESSID_MAX_SIZE+2, 1); | ||
1013 | if (err) | ||
1014 | return err; | ||
1015 | } | ||
1016 | zd->monitor=monitor; | ||
1017 | /* If monitor mode is set we don't actually turn it on here since it | ||
1018 | * is done during mac reset anyway (see zd1201_mac_enable). | ||
1019 | */ | ||
1020 | |||
1021 | zd1201_mac_reset(zd); | ||
1022 | |||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | static int zd1201_get_mode(struct net_device *dev, | ||
1027 | struct iw_request_info *info, __u32 *mode, char *extra) | ||
1028 | { | ||
1029 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1030 | short porttype; | ||
1031 | int err; | ||
1032 | |||
1033 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype); | ||
1034 | if (err) | ||
1035 | return err; | ||
1036 | switch(porttype) { | ||
1037 | case ZD1201_PORTTYPE_IBSS: | ||
1038 | *mode = IW_MODE_ADHOC; | ||
1039 | break; | ||
1040 | case ZD1201_PORTTYPE_BSS: | ||
1041 | *mode = IW_MODE_INFRA; | ||
1042 | break; | ||
1043 | case ZD1201_PORTTYPE_WDS: | ||
1044 | *mode = IW_MODE_REPEAT; | ||
1045 | break; | ||
1046 | case ZD1201_PORTTYPE_PSEUDOIBSS: | ||
1047 | *mode = 8;/* No Pseudo-IBSS... */ | ||
1048 | break; | ||
1049 | case ZD1201_PORTTYPE_AP: | ||
1050 | *mode = IW_MODE_MASTER; | ||
1051 | break; | ||
1052 | default: | ||
1053 | dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n", | ||
1054 | porttype); | ||
1055 | *mode = IW_MODE_AUTO; | ||
1056 | } | ||
1057 | if (zd->monitor) | ||
1058 | *mode = IW_MODE_MONITOR; | ||
1059 | |||
1060 | return 0; | ||
1061 | } | ||
1062 | |||
1063 | static int zd1201_get_range(struct net_device *dev, | ||
1064 | struct iw_request_info *info, struct iw_point *wrq, char *extra) | ||
1065 | { | ||
1066 | struct iw_range *range = (struct iw_range *)extra; | ||
1067 | |||
1068 | wrq->length = sizeof(struct iw_range); | ||
1069 | memset(range, 0, sizeof(struct iw_range)); | ||
1070 | range->we_version_compiled = WIRELESS_EXT; | ||
1071 | range->we_version_source = WIRELESS_EXT; | ||
1072 | |||
1073 | range->max_qual.qual = 128; | ||
1074 | range->max_qual.level = 128; | ||
1075 | range->max_qual.noise = 128; | ||
1076 | range->max_qual.updated = 7; | ||
1077 | |||
1078 | range->encoding_size[0] = 5; | ||
1079 | range->encoding_size[1] = 13; | ||
1080 | range->num_encoding_sizes = 2; | ||
1081 | range->max_encoding_tokens = ZD1201_NUMKEYS; | ||
1082 | |||
1083 | range->num_bitrates = 4; | ||
1084 | range->bitrate[0] = 1000000; | ||
1085 | range->bitrate[1] = 2000000; | ||
1086 | range->bitrate[2] = 5500000; | ||
1087 | range->bitrate[3] = 11000000; | ||
1088 | |||
1089 | range->min_rts = 0; | ||
1090 | range->min_frag = ZD1201_FRAGMIN; | ||
1091 | range->max_rts = ZD1201_RTSMAX; | ||
1092 | range->min_frag = ZD1201_FRAGMAX; | ||
1093 | |||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | /* Little bit of magic here: we only get the quality if we poll | ||
1098 | * for it, and we never get an actual request to trigger such | ||
1099 | * a poll. Therefore we 'assume' that the user will soon ask for | ||
1100 | * the stats after asking the bssid. | ||
1101 | */ | ||
1102 | static int zd1201_get_wap(struct net_device *dev, | ||
1103 | struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) | ||
1104 | { | ||
1105 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1106 | unsigned char buffer[6]; | ||
1107 | |||
1108 | if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) { | ||
1109 | /* Unfortunately the quality and noise reported is useless. | ||
1110 | they seem to be accumulators that increase until you | ||
1111 | read them, unless we poll on a fixed interval we can't | ||
1112 | use them | ||
1113 | */ | ||
1114 | /*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/ | ||
1115 | zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]); | ||
1116 | /*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/ | ||
1117 | zd->iwstats.qual.updated = 2; | ||
1118 | } | ||
1119 | |||
1120 | return zd1201_getconfig(zd,ZD1201_RID_CURRENTBSSID,ap_addr->sa_data,6); | ||
1121 | } | ||
1122 | |||
1123 | static int zd1201_set_scan(struct net_device *dev, | ||
1124 | struct iw_request_info *info, struct iw_point *srq, char *extra) | ||
1125 | { | ||
1126 | /* We do everything in get_scan */ | ||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1130 | static int zd1201_get_scan(struct net_device *dev, | ||
1131 | struct iw_request_info *info, struct iw_point *srq, char *extra) | ||
1132 | { | ||
1133 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1134 | int err, i, j, enabled_save; | ||
1135 | struct iw_event iwe; | ||
1136 | char *cev = extra; | ||
1137 | char *end_buf = extra + IW_SCAN_MAX_DATA; | ||
1138 | |||
1139 | /* No scanning in AP mode */ | ||
1140 | if (zd->ap) | ||
1141 | return -EOPNOTSUPP; | ||
1142 | |||
1143 | /* Scan doesn't seem to work if disabled */ | ||
1144 | enabled_save = zd->mac_enabled; | ||
1145 | zd1201_enable(zd); | ||
1146 | |||
1147 | zd->rxdatas = 0; | ||
1148 | err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, | ||
1149 | ZD1201_INQ_SCANRESULTS, 0, 0); | ||
1150 | if (err) | ||
1151 | return err; | ||
1152 | |||
1153 | wait_event_interruptible(zd->rxdataq, zd->rxdatas); | ||
1154 | if (!zd->rxlen) | ||
1155 | return -EIO; | ||
1156 | |||
1157 | if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS) | ||
1158 | return -EIO; | ||
1159 | |||
1160 | for(i=8; i<zd->rxlen; i+=62) { | ||
1161 | iwe.cmd = SIOCGIWAP; | ||
1162 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
1163 | memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); | ||
1164 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); | ||
1165 | |||
1166 | iwe.cmd = SIOCGIWESSID; | ||
1167 | iwe.u.data.length = zd->rxdata[i+16]; | ||
1168 | iwe.u.data.flags = 1; | ||
1169 | cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18); | ||
1170 | |||
1171 | iwe.cmd = SIOCGIWMODE; | ||
1172 | if (zd->rxdata[i+14]&0x01) | ||
1173 | iwe.u.mode = IW_MODE_MASTER; | ||
1174 | else | ||
1175 | iwe.u.mode = IW_MODE_ADHOC; | ||
1176 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); | ||
1177 | |||
1178 | iwe.cmd = SIOCGIWFREQ; | ||
1179 | iwe.u.freq.m = zd->rxdata[i+0]; | ||
1180 | iwe.u.freq.e = 0; | ||
1181 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); | ||
1182 | |||
1183 | iwe.cmd = SIOCGIWRATE; | ||
1184 | iwe.u.bitrate.fixed = 0; | ||
1185 | iwe.u.bitrate.disabled = 0; | ||
1186 | for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { | ||
1187 | iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; | ||
1188 | cev=iwe_stream_add_event(cev, end_buf, &iwe, | ||
1189 | IW_EV_PARAM_LEN); | ||
1190 | } | ||
1191 | |||
1192 | iwe.cmd = SIOCGIWENCODE; | ||
1193 | iwe.u.data.length = 0; | ||
1194 | if (zd->rxdata[i+14]&0x10) | ||
1195 | iwe.u.data.flags = IW_ENCODE_ENABLED; | ||
1196 | else | ||
1197 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
1198 | cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); | ||
1199 | |||
1200 | iwe.cmd = IWEVQUAL; | ||
1201 | iwe.u.qual.qual = zd->rxdata[i+4]; | ||
1202 | iwe.u.qual.noise= zd->rxdata[i+2]/10-100; | ||
1203 | iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; | ||
1204 | iwe.u.qual.updated = 7; | ||
1205 | cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); | ||
1206 | } | ||
1207 | |||
1208 | if (!enabled_save) | ||
1209 | zd1201_disable(zd); | ||
1210 | |||
1211 | srq->length = cev - extra; | ||
1212 | srq->flags = 0; | ||
1213 | |||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | static int zd1201_set_essid(struct net_device *dev, | ||
1218 | struct iw_request_info *info, struct iw_point *data, char *essid) | ||
1219 | { | ||
1220 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1221 | |||
1222 | if (data->length > IW_ESSID_MAX_SIZE) | ||
1223 | return -EINVAL; | ||
1224 | if (data->length < 1) | ||
1225 | data->length = 1; | ||
1226 | zd->essidlen = data->length-1; | ||
1227 | memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1); | ||
1228 | memcpy(zd->essid, essid, data->length); | ||
1229 | return zd1201_join(zd, zd->essid, zd->essidlen); | ||
1230 | } | ||
1231 | |||
1232 | static int zd1201_get_essid(struct net_device *dev, | ||
1233 | struct iw_request_info *info, struct iw_point *data, char *essid) | ||
1234 | { | ||
1235 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1236 | |||
1237 | memcpy(essid, zd->essid, zd->essidlen); | ||
1238 | data->flags = 1; | ||
1239 | data->length = zd->essidlen; | ||
1240 | |||
1241 | return 0; | ||
1242 | } | ||
1243 | |||
1244 | static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, | ||
1245 | struct iw_point *data, char *nick) | ||
1246 | { | ||
1247 | strcpy(nick, "zd1201"); | ||
1248 | data->flags = 1; | ||
1249 | data->length = strlen(nick); | ||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | static int zd1201_set_rate(struct net_device *dev, | ||
1254 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
1255 | { | ||
1256 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1257 | short rate; | ||
1258 | int err; | ||
1259 | |||
1260 | switch (rrq->value) { | ||
1261 | case 1000000: | ||
1262 | rate = ZD1201_RATEB1; | ||
1263 | break; | ||
1264 | case 2000000: | ||
1265 | rate = ZD1201_RATEB2; | ||
1266 | break; | ||
1267 | case 5500000: | ||
1268 | rate = ZD1201_RATEB5; | ||
1269 | break; | ||
1270 | case 11000000: | ||
1271 | default: | ||
1272 | rate = ZD1201_RATEB11; | ||
1273 | break; | ||
1274 | } | ||
1275 | if (!rrq->fixed) { /* Also enable all lower bitrates */ | ||
1276 | rate |= rate-1; | ||
1277 | } | ||
1278 | |||
1279 | err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate); | ||
1280 | if (err) | ||
1281 | return err; | ||
1282 | |||
1283 | return zd1201_mac_reset(zd); | ||
1284 | } | ||
1285 | |||
1286 | static int zd1201_get_rate(struct net_device *dev, | ||
1287 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
1288 | { | ||
1289 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1290 | short rate; | ||
1291 | int err; | ||
1292 | |||
1293 | err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate); | ||
1294 | if (err) | ||
1295 | return err; | ||
1296 | |||
1297 | switch(rate) { | ||
1298 | case 1: | ||
1299 | rrq->value = 1000000; | ||
1300 | break; | ||
1301 | case 2: | ||
1302 | rrq->value = 2000000; | ||
1303 | break; | ||
1304 | case 5: | ||
1305 | rrq->value = 5500000; | ||
1306 | break; | ||
1307 | case 11: | ||
1308 | rrq->value = 11000000; | ||
1309 | break; | ||
1310 | default: | ||
1311 | rrq->value = 0; | ||
1312 | } | ||
1313 | rrq->fixed = 0; | ||
1314 | rrq->disabled = 0; | ||
1315 | |||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1319 | static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, | ||
1320 | struct iw_param *rts, char *extra) | ||
1321 | { | ||
1322 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1323 | int err; | ||
1324 | short val = rts->value; | ||
1325 | |||
1326 | if (rts->disabled || !rts->fixed) | ||
1327 | val = ZD1201_RTSMAX; | ||
1328 | if (val > ZD1201_RTSMAX) | ||
1329 | return -EINVAL; | ||
1330 | if (val < 0) | ||
1331 | return -EINVAL; | ||
1332 | |||
1333 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val); | ||
1334 | if (err) | ||
1335 | return err; | ||
1336 | return zd1201_mac_reset(zd); | ||
1337 | } | ||
1338 | |||
1339 | static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, | ||
1340 | struct iw_param *rts, char *extra) | ||
1341 | { | ||
1342 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1343 | short rtst; | ||
1344 | int err; | ||
1345 | |||
1346 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst); | ||
1347 | if (err) | ||
1348 | return err; | ||
1349 | rts->value = rtst; | ||
1350 | rts->disabled = (rts->value == ZD1201_RTSMAX); | ||
1351 | rts->fixed = 1; | ||
1352 | |||
1353 | return 0; | ||
1354 | } | ||
1355 | |||
1356 | static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, | ||
1357 | struct iw_param *frag, char *extra) | ||
1358 | { | ||
1359 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1360 | int err; | ||
1361 | short val = frag->value; | ||
1362 | |||
1363 | if (frag->disabled || !frag->fixed) | ||
1364 | val = ZD1201_FRAGMAX; | ||
1365 | if (val > ZD1201_FRAGMAX) | ||
1366 | return -EINVAL; | ||
1367 | if (val < ZD1201_FRAGMIN) | ||
1368 | return -EINVAL; | ||
1369 | if (val & 1) | ||
1370 | return -EINVAL; | ||
1371 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val); | ||
1372 | if (err) | ||
1373 | return err; | ||
1374 | return zd1201_mac_reset(zd); | ||
1375 | } | ||
1376 | |||
1377 | static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, | ||
1378 | struct iw_param *frag, char *extra) | ||
1379 | { | ||
1380 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1381 | short fragt; | ||
1382 | int err; | ||
1383 | |||
1384 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt); | ||
1385 | if (err) | ||
1386 | return err; | ||
1387 | frag->value = fragt; | ||
1388 | frag->disabled = (frag->value == ZD1201_FRAGMAX); | ||
1389 | frag->fixed = 1; | ||
1390 | |||
1391 | return 0; | ||
1392 | } | ||
1393 | |||
1394 | static int zd1201_set_retry(struct net_device *dev, | ||
1395 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
1396 | { | ||
1397 | return 0; | ||
1398 | } | ||
1399 | |||
1400 | static int zd1201_get_retry(struct net_device *dev, | ||
1401 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
1402 | { | ||
1403 | return 0; | ||
1404 | } | ||
1405 | |||
1406 | static int zd1201_set_encode(struct net_device *dev, | ||
1407 | struct iw_request_info *info, struct iw_point *erq, char *key) | ||
1408 | { | ||
1409 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1410 | short i; | ||
1411 | int err, rid; | ||
1412 | |||
1413 | if (erq->length > ZD1201_MAXKEYLEN) | ||
1414 | return -EINVAL; | ||
1415 | |||
1416 | i = (erq->flags & IW_ENCODE_INDEX)-1; | ||
1417 | if (i == -1) { | ||
1418 | err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i); | ||
1419 | if (err) | ||
1420 | return err; | ||
1421 | } else { | ||
1422 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i); | ||
1423 | if (err) | ||
1424 | return err; | ||
1425 | } | ||
1426 | |||
1427 | if (i < 0 || i >= ZD1201_NUMKEYS) | ||
1428 | return -EINVAL; | ||
1429 | |||
1430 | rid = ZD1201_RID_CNFDEFAULTKEY0 + i; | ||
1431 | err = zd1201_setconfig(zd, rid, key, erq->length, 1); | ||
1432 | if (err) | ||
1433 | return err; | ||
1434 | zd->encode_keylen[i] = erq->length; | ||
1435 | memcpy(zd->encode_keys[i], key, erq->length); | ||
1436 | |||
1437 | i=0; | ||
1438 | if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) { | ||
1439 | i |= 0x01; | ||
1440 | zd->encode_enabled = 1; | ||
1441 | } else | ||
1442 | zd->encode_enabled = 0; | ||
1443 | if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) { | ||
1444 | i |= 0x02; | ||
1445 | zd->encode_restricted = 1; | ||
1446 | } else | ||
1447 | zd->encode_restricted = 0; | ||
1448 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i); | ||
1449 | if (err) | ||
1450 | return err; | ||
1451 | |||
1452 | if (zd->encode_enabled) | ||
1453 | i = ZD1201_CNFAUTHENTICATION_SHAREDKEY; | ||
1454 | else | ||
1455 | i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; | ||
1456 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i); | ||
1457 | if (err) | ||
1458 | return err; | ||
1459 | |||
1460 | return zd1201_mac_reset(zd); | ||
1461 | } | ||
1462 | |||
1463 | static int zd1201_get_encode(struct net_device *dev, | ||
1464 | struct iw_request_info *info, struct iw_point *erq, char *key) | ||
1465 | { | ||
1466 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1467 | short i; | ||
1468 | int err; | ||
1469 | |||
1470 | if (zd->encode_enabled) | ||
1471 | erq->flags = IW_ENCODE_ENABLED; | ||
1472 | else | ||
1473 | erq->flags = IW_ENCODE_DISABLED; | ||
1474 | if (zd->encode_restricted) | ||
1475 | erq->flags |= IW_ENCODE_RESTRICTED; | ||
1476 | else | ||
1477 | erq->flags |= IW_ENCODE_OPEN; | ||
1478 | |||
1479 | i = (erq->flags & IW_ENCODE_INDEX) -1; | ||
1480 | if (i == -1) { | ||
1481 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i); | ||
1482 | if (err) | ||
1483 | return err; | ||
1484 | } | ||
1485 | if (i<0 || i>= ZD1201_NUMKEYS) | ||
1486 | return -EINVAL; | ||
1487 | |||
1488 | erq->flags |= i+1; | ||
1489 | |||
1490 | erq->length = zd->encode_keylen[i]; | ||
1491 | memcpy(key, zd->encode_keys[i], erq->length); | ||
1492 | |||
1493 | return 0; | ||
1494 | } | ||
1495 | |||
1496 | static int zd1201_set_power(struct net_device *dev, | ||
1497 | struct iw_request_info *info, struct iw_param *vwrq, char *extra) | ||
1498 | { | ||
1499 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1500 | short enabled, duration, level; | ||
1501 | int err; | ||
1502 | |||
1503 | enabled = vwrq->disabled ? 0 : 1; | ||
1504 | if (enabled) { | ||
1505 | if (vwrq->flags & IW_POWER_PERIOD) { | ||
1506 | duration = vwrq->value; | ||
1507 | err = zd1201_setconfig16(zd, | ||
1508 | ZD1201_RID_CNFMAXSLEEPDURATION, duration); | ||
1509 | if (err) | ||
1510 | return err; | ||
1511 | goto out; | ||
1512 | } | ||
1513 | if (vwrq->flags & IW_POWER_TIMEOUT) { | ||
1514 | err = zd1201_getconfig16(zd, | ||
1515 | ZD1201_RID_CNFMAXSLEEPDURATION, &duration); | ||
1516 | if (err) | ||
1517 | return err; | ||
1518 | level = vwrq->value * 4 / duration; | ||
1519 | if (level > 4) | ||
1520 | level = 4; | ||
1521 | if (level < 0) | ||
1522 | level = 0; | ||
1523 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS, | ||
1524 | level); | ||
1525 | if (err) | ||
1526 | return err; | ||
1527 | goto out; | ||
1528 | } | ||
1529 | return -EINVAL; | ||
1530 | } | ||
1531 | out: | ||
1532 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled); | ||
1533 | if (err) | ||
1534 | return err; | ||
1535 | |||
1536 | return 0; | ||
1537 | } | ||
1538 | |||
1539 | static int zd1201_get_power(struct net_device *dev, | ||
1540 | struct iw_request_info *info, struct iw_param *vwrq, char *extra) | ||
1541 | { | ||
1542 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1543 | short enabled, level, duration; | ||
1544 | int err; | ||
1545 | |||
1546 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled); | ||
1547 | if (err) | ||
1548 | return err; | ||
1549 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level); | ||
1550 | if (err) | ||
1551 | return err; | ||
1552 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration); | ||
1553 | if (err) | ||
1554 | return err; | ||
1555 | vwrq->disabled = enabled ? 0 : 1; | ||
1556 | if (vwrq->flags & IW_POWER_TYPE) { | ||
1557 | if (vwrq->flags & IW_POWER_PERIOD) { | ||
1558 | vwrq->value = duration; | ||
1559 | vwrq->flags = IW_POWER_PERIOD; | ||
1560 | } else { | ||
1561 | vwrq->value = duration * level / 4; | ||
1562 | vwrq->flags = IW_POWER_TIMEOUT; | ||
1563 | } | ||
1564 | } | ||
1565 | if (vwrq->flags & IW_POWER_MODE) { | ||
1566 | if (enabled && level) | ||
1567 | vwrq->flags = IW_POWER_UNICAST_R; | ||
1568 | else | ||
1569 | vwrq->flags = IW_POWER_ALL_R; | ||
1570 | } | ||
1571 | |||
1572 | return 0; | ||
1573 | } | ||
1574 | |||
1575 | |||
1576 | static const iw_handler zd1201_iw_handler[] = | ||
1577 | { | ||
1578 | (iw_handler) zd1201_config_commit, /* SIOCSIWCOMMIT */ | ||
1579 | (iw_handler) zd1201_get_name, /* SIOCGIWNAME */ | ||
1580 | (iw_handler) NULL, /* SIOCSIWNWID */ | ||
1581 | (iw_handler) NULL, /* SIOCGIWNWID */ | ||
1582 | (iw_handler) zd1201_set_freq, /* SIOCSIWFREQ */ | ||
1583 | (iw_handler) zd1201_get_freq, /* SIOCGIWFREQ */ | ||
1584 | (iw_handler) zd1201_set_mode, /* SIOCSIWMODE */ | ||
1585 | (iw_handler) zd1201_get_mode, /* SIOCGIWMODE */ | ||
1586 | (iw_handler) NULL, /* SIOCSIWSENS */ | ||
1587 | (iw_handler) NULL, /* SIOCGIWSENS */ | ||
1588 | (iw_handler) NULL, /* SIOCSIWRANGE */ | ||
1589 | (iw_handler) zd1201_get_range, /* SIOCGIWRANGE */ | ||
1590 | (iw_handler) NULL, /* SIOCSIWPRIV */ | ||
1591 | (iw_handler) NULL, /* SIOCGIWPRIV */ | ||
1592 | (iw_handler) NULL, /* SIOCSIWSTATS */ | ||
1593 | (iw_handler) NULL, /* SIOCGIWSTATS */ | ||
1594 | (iw_handler) NULL, /* SIOCSIWSPY */ | ||
1595 | (iw_handler) NULL, /* SIOCGIWSPY */ | ||
1596 | (iw_handler) NULL, /* -- hole -- */ | ||
1597 | (iw_handler) NULL, /* -- hole -- */ | ||
1598 | (iw_handler) NULL/*zd1201_set_wap*/, /* SIOCSIWAP */ | ||
1599 | (iw_handler) zd1201_get_wap, /* SIOCGIWAP */ | ||
1600 | (iw_handler) NULL, /* -- hole -- */ | ||
1601 | (iw_handler) NULL, /* SIOCGIWAPLIST */ | ||
1602 | (iw_handler) zd1201_set_scan, /* SIOCSIWSCAN */ | ||
1603 | (iw_handler) zd1201_get_scan, /* SIOCGIWSCAN */ | ||
1604 | (iw_handler) zd1201_set_essid, /* SIOCSIWESSID */ | ||
1605 | (iw_handler) zd1201_get_essid, /* SIOCGIWESSID */ | ||
1606 | (iw_handler) NULL, /* SIOCSIWNICKN */ | ||
1607 | (iw_handler) zd1201_get_nick, /* SIOCGIWNICKN */ | ||
1608 | (iw_handler) NULL, /* -- hole -- */ | ||
1609 | (iw_handler) NULL, /* -- hole -- */ | ||
1610 | (iw_handler) zd1201_set_rate, /* SIOCSIWRATE */ | ||
1611 | (iw_handler) zd1201_get_rate, /* SIOCGIWRATE */ | ||
1612 | (iw_handler) zd1201_set_rts, /* SIOCSIWRTS */ | ||
1613 | (iw_handler) zd1201_get_rts, /* SIOCGIWRTS */ | ||
1614 | (iw_handler) zd1201_set_frag, /* SIOCSIWFRAG */ | ||
1615 | (iw_handler) zd1201_get_frag, /* SIOCGIWFRAG */ | ||
1616 | (iw_handler) NULL, /* SIOCSIWTXPOW */ | ||
1617 | (iw_handler) NULL, /* SIOCGIWTXPOW */ | ||
1618 | (iw_handler) zd1201_set_retry, /* SIOCSIWRETRY */ | ||
1619 | (iw_handler) zd1201_get_retry, /* SIOCGIWRETRY */ | ||
1620 | (iw_handler) zd1201_set_encode, /* SIOCSIWENCODE */ | ||
1621 | (iw_handler) zd1201_get_encode, /* SIOCGIWENCODE */ | ||
1622 | (iw_handler) zd1201_set_power, /* SIOCSIWPOWER */ | ||
1623 | (iw_handler) zd1201_get_power, /* SIOCGIWPOWER */ | ||
1624 | }; | ||
1625 | |||
1626 | static int zd1201_set_hostauth(struct net_device *dev, | ||
1627 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
1628 | { | ||
1629 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1630 | int err; | ||
1631 | |||
1632 | if (!zd->ap) | ||
1633 | return -EOPNOTSUPP; | ||
1634 | |||
1635 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value); | ||
1636 | if (err) | ||
1637 | return err; | ||
1638 | return 0; | ||
1639 | } | ||
1640 | |||
1641 | static int zd1201_get_hostauth(struct net_device *dev, | ||
1642 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
1643 | { | ||
1644 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1645 | short hostauth; | ||
1646 | int err; | ||
1647 | |||
1648 | if (!zd->ap) | ||
1649 | return -EOPNOTSUPP; | ||
1650 | |||
1651 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth); | ||
1652 | if (err) | ||
1653 | return err; | ||
1654 | rrq->value = hostauth; | ||
1655 | rrq->fixed = 1; | ||
1656 | |||
1657 | return 0; | ||
1658 | } | ||
1659 | |||
1660 | static int zd1201_auth_sta(struct net_device *dev, | ||
1661 | struct iw_request_info *info, struct sockaddr *sta, char *extra) | ||
1662 | { | ||
1663 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1664 | unsigned char buffer[10]; | ||
1665 | |||
1666 | if (!zd->ap) | ||
1667 | return -EOPNOTSUPP; | ||
1668 | |||
1669 | memcpy(buffer, sta->sa_data, ETH_ALEN); | ||
1670 | *(short*)(buffer+6) = 0; /* 0==success, 1==failure */ | ||
1671 | *(short*)(buffer+8) = 0; | ||
1672 | |||
1673 | return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1); | ||
1674 | } | ||
1675 | |||
1676 | static int zd1201_set_maxassoc(struct net_device *dev, | ||
1677 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
1678 | { | ||
1679 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1680 | int err; | ||
1681 | |||
1682 | if (!zd->ap) | ||
1683 | return -EOPNOTSUPP; | ||
1684 | |||
1685 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value); | ||
1686 | if (err) | ||
1687 | return err; | ||
1688 | return 0; | ||
1689 | } | ||
1690 | |||
1691 | static int zd1201_get_maxassoc(struct net_device *dev, | ||
1692 | struct iw_request_info *info, struct iw_param *rrq, char *extra) | ||
1693 | { | ||
1694 | struct zd1201 *zd = (struct zd1201 *)dev->priv; | ||
1695 | short maxassoc; | ||
1696 | int err; | ||
1697 | |||
1698 | if (!zd->ap) | ||
1699 | return -EOPNOTSUPP; | ||
1700 | |||
1701 | err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc); | ||
1702 | if (err) | ||
1703 | return err; | ||
1704 | rrq->value = maxassoc; | ||
1705 | rrq->fixed = 1; | ||
1706 | |||
1707 | return 0; | ||
1708 | } | ||
1709 | |||
1710 | static const iw_handler zd1201_private_handler[] = { | ||
1711 | (iw_handler) zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */ | ||
1712 | (iw_handler) zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */ | ||
1713 | (iw_handler) zd1201_auth_sta, /* ZD1201SIWAUTHSTA */ | ||
1714 | (iw_handler) NULL, /* nothing to get */ | ||
1715 | (iw_handler) zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */ | ||
1716 | (iw_handler) zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */ | ||
1717 | }; | ||
1718 | |||
1719 | static const struct iw_priv_args zd1201_private_args[] = { | ||
1720 | { ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
1721 | IW_PRIV_TYPE_NONE, "sethostauth" }, | ||
1722 | { ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE, | ||
1723 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" }, | ||
1724 | { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, | ||
1725 | IW_PRIV_TYPE_NONE, "authstation" }, | ||
1726 | { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
1727 | IW_PRIV_TYPE_NONE, "setmaxassoc" }, | ||
1728 | { ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE, | ||
1729 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" }, | ||
1730 | }; | ||
1731 | |||
1732 | static const struct iw_handler_def zd1201_iw_handlers = { | ||
1733 | .num_standard = ARRAY_SIZE(zd1201_iw_handler), | ||
1734 | .num_private = ARRAY_SIZE(zd1201_private_handler), | ||
1735 | .num_private_args = ARRAY_SIZE(zd1201_private_args), | ||
1736 | .standard = (iw_handler *)zd1201_iw_handler, | ||
1737 | .private = (iw_handler *)zd1201_private_handler, | ||
1738 | .private_args = (struct iw_priv_args *) zd1201_private_args, | ||
1739 | .get_wireless_stats = zd1201_get_wireless_stats, | ||
1740 | }; | ||
1741 | |||
1742 | static int zd1201_probe(struct usb_interface *interface, | ||
1743 | const struct usb_device_id *id) | ||
1744 | { | ||
1745 | struct zd1201 *zd; | ||
1746 | struct usb_device *usb; | ||
1747 | int i, err; | ||
1748 | short porttype; | ||
1749 | char buf[IW_ESSID_MAX_SIZE+2]; | ||
1750 | |||
1751 | usb = interface_to_usbdev(interface); | ||
1752 | |||
1753 | zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL); | ||
1754 | if (!zd) | ||
1755 | return -ENOMEM; | ||
1756 | zd->ap = ap; | ||
1757 | zd->usb = usb; | ||
1758 | zd->removed = 0; | ||
1759 | init_waitqueue_head(&zd->rxdataq); | ||
1760 | INIT_HLIST_HEAD(&zd->fraglist); | ||
1761 | |||
1762 | err = zd1201_fw_upload(usb, zd->ap); | ||
1763 | if (err) { | ||
1764 | dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err); | ||
1765 | goto err_zd; | ||
1766 | } | ||
1767 | |||
1768 | zd->endp_in = 1; | ||
1769 | zd->endp_out = 1; | ||
1770 | zd->endp_out2 = 2; | ||
1771 | zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1772 | zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1773 | if (!zd->rx_urb || !zd->tx_urb) | ||
1774 | goto err_zd; | ||
1775 | |||
1776 | for(i = 0; i<100; i++) | ||
1777 | udelay(1000); | ||
1778 | |||
1779 | err = zd1201_drvr_start(zd); | ||
1780 | if (err) | ||
1781 | goto err_zd; | ||
1782 | |||
1783 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312); | ||
1784 | if (err) | ||
1785 | goto err_start; | ||
1786 | |||
1787 | err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, | ||
1788 | ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11); | ||
1789 | if (err) | ||
1790 | goto err_start; | ||
1791 | |||
1792 | zd->dev = alloc_etherdev(0); | ||
1793 | if (!zd->dev) | ||
1794 | goto err_start; | ||
1795 | |||
1796 | zd->dev->priv = zd; | ||
1797 | zd->dev->open = zd1201_net_open; | ||
1798 | zd->dev->stop = zd1201_net_stop; | ||
1799 | zd->dev->get_stats = zd1201_get_stats; | ||
1800 | zd->dev->wireless_handlers = | ||
1801 | (struct iw_handler_def *)&zd1201_iw_handlers; | ||
1802 | zd->dev->hard_start_xmit = zd1201_hard_start_xmit; | ||
1803 | zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT; | ||
1804 | zd->dev->tx_timeout = zd1201_tx_timeout; | ||
1805 | zd->dev->set_multicast_list = zd1201_set_multicast; | ||
1806 | zd->dev->set_mac_address = zd1201_set_mac_address; | ||
1807 | strcpy(zd->dev->name, "wlan%d"); | ||
1808 | |||
1809 | err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, | ||
1810 | zd->dev->dev_addr, zd->dev->addr_len); | ||
1811 | if (err) | ||
1812 | goto err_net; | ||
1813 | |||
1814 | /* Set wildcard essid to match zd->essid */ | ||
1815 | *(__le16 *)buf = cpu_to_le16(0); | ||
1816 | err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, | ||
1817 | IW_ESSID_MAX_SIZE+2, 1); | ||
1818 | if (err) | ||
1819 | goto err_net; | ||
1820 | |||
1821 | if (zd->ap) | ||
1822 | porttype = ZD1201_PORTTYPE_AP; | ||
1823 | else | ||
1824 | porttype = ZD1201_PORTTYPE_BSS; | ||
1825 | err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); | ||
1826 | if (err) | ||
1827 | goto err_net; | ||
1828 | |||
1829 | SET_NETDEV_DEV(zd->dev, &usb->dev); | ||
1830 | |||
1831 | err = register_netdev(zd->dev); | ||
1832 | if (err) | ||
1833 | goto err_net; | ||
1834 | dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", | ||
1835 | zd->dev->name); | ||
1836 | |||
1837 | usb_set_intfdata(interface, zd); | ||
1838 | return 0; | ||
1839 | |||
1840 | err_net: | ||
1841 | free_netdev(zd->dev); | ||
1842 | err_start: | ||
1843 | /* Leave the device in reset state */ | ||
1844 | zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); | ||
1845 | err_zd: | ||
1846 | if (zd->tx_urb) | ||
1847 | usb_free_urb(zd->tx_urb); | ||
1848 | if (zd->rx_urb) | ||
1849 | usb_free_urb(zd->rx_urb); | ||
1850 | kfree(zd); | ||
1851 | return err; | ||
1852 | } | ||
1853 | |||
1854 | static void zd1201_disconnect(struct usb_interface *interface) | ||
1855 | { | ||
1856 | struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface); | ||
1857 | struct hlist_node *node, *node2; | ||
1858 | struct zd1201_frag *frag; | ||
1859 | |||
1860 | if (!zd) | ||
1861 | return; | ||
1862 | usb_set_intfdata(interface, NULL); | ||
1863 | if (zd->dev) { | ||
1864 | unregister_netdev(zd->dev); | ||
1865 | free_netdev(zd->dev); | ||
1866 | } | ||
1867 | |||
1868 | hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) { | ||
1869 | hlist_del_init(&frag->fnode); | ||
1870 | kfree_skb(frag->skb); | ||
1871 | kfree(frag); | ||
1872 | } | ||
1873 | |||
1874 | if (zd->tx_urb) { | ||
1875 | usb_kill_urb(zd->tx_urb); | ||
1876 | usb_free_urb(zd->tx_urb); | ||
1877 | } | ||
1878 | if (zd->rx_urb) { | ||
1879 | usb_kill_urb(zd->rx_urb); | ||
1880 | usb_free_urb(zd->rx_urb); | ||
1881 | } | ||
1882 | kfree(zd); | ||
1883 | } | ||
1884 | |||
1885 | #ifdef CONFIG_PM | ||
1886 | |||
1887 | static int zd1201_suspend(struct usb_interface *interface, | ||
1888 | pm_message_t message) | ||
1889 | { | ||
1890 | struct zd1201 *zd = usb_get_intfdata(interface); | ||
1891 | |||
1892 | netif_device_detach(zd->dev); | ||
1893 | |||
1894 | zd->was_enabled = zd->mac_enabled; | ||
1895 | |||
1896 | if (zd->was_enabled) | ||
1897 | return zd1201_disable(zd); | ||
1898 | else | ||
1899 | return 0; | ||
1900 | } | ||
1901 | |||
1902 | static int zd1201_resume(struct usb_interface *interface) | ||
1903 | { | ||
1904 | struct zd1201 *zd = usb_get_intfdata(interface); | ||
1905 | |||
1906 | if (!zd || !zd->dev) | ||
1907 | return -ENODEV; | ||
1908 | |||
1909 | netif_device_attach(zd->dev); | ||
1910 | |||
1911 | if (zd->was_enabled) | ||
1912 | return zd1201_enable(zd); | ||
1913 | else | ||
1914 | return 0; | ||
1915 | } | ||
1916 | |||
1917 | #else | ||
1918 | |||
1919 | #define zd1201_suspend NULL | ||
1920 | #define zd1201_resume NULL | ||
1921 | |||
1922 | #endif | ||
1923 | |||
1924 | static struct usb_driver zd1201_usb = { | ||
1925 | .name = "zd1201", | ||
1926 | .probe = zd1201_probe, | ||
1927 | .disconnect = zd1201_disconnect, | ||
1928 | .id_table = zd1201_table, | ||
1929 | .suspend = zd1201_suspend, | ||
1930 | .resume = zd1201_resume, | ||
1931 | }; | ||
1932 | |||
1933 | static int __init zd1201_init(void) | ||
1934 | { | ||
1935 | return usb_register(&zd1201_usb); | ||
1936 | } | ||
1937 | |||
1938 | static void __exit zd1201_cleanup(void) | ||
1939 | { | ||
1940 | usb_deregister(&zd1201_usb); | ||
1941 | } | ||
1942 | |||
1943 | module_init(zd1201_init); | ||
1944 | module_exit(zd1201_cleanup); | ||
diff --git a/drivers/usb/net/zd1201.h b/drivers/usb/net/zd1201.h deleted file mode 100644 index 235f0ee34b24..000000000000 --- a/drivers/usb/net/zd1201.h +++ /dev/null | |||
@@ -1,148 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * Parts of this driver have been derived from a wlan-ng version | ||
9 | * modified by ZyDAS. | ||
10 | * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. | ||
11 | */ | ||
12 | |||
13 | #ifndef _INCLUDE_ZD1201_H_ | ||
14 | #define _INCLUDE_ZD1201_H_ | ||
15 | |||
16 | #define ZD1201_NUMKEYS 4 | ||
17 | #define ZD1201_MAXKEYLEN 13 | ||
18 | #define ZD1201_MAXMULTI 16 | ||
19 | #define ZD1201_FRAGMAX 2500 | ||
20 | #define ZD1201_FRAGMIN 256 | ||
21 | #define ZD1201_RTSMAX 2500 | ||
22 | |||
23 | #define ZD1201_RXSIZE 3000 | ||
24 | |||
25 | struct zd1201 { | ||
26 | struct usb_device *usb; | ||
27 | int removed; | ||
28 | struct net_device *dev; | ||
29 | struct net_device_stats stats; | ||
30 | struct iw_statistics iwstats; | ||
31 | |||
32 | int endp_in; | ||
33 | int endp_out; | ||
34 | int endp_out2; | ||
35 | struct urb *rx_urb; | ||
36 | struct urb *tx_urb; | ||
37 | |||
38 | unsigned char rxdata[ZD1201_RXSIZE]; | ||
39 | int rxlen; | ||
40 | wait_queue_head_t rxdataq; | ||
41 | int rxdatas; | ||
42 | struct hlist_head fraglist; | ||
43 | unsigned char txdata[ZD1201_RXSIZE]; | ||
44 | |||
45 | int ap; | ||
46 | char essid[IW_ESSID_MAX_SIZE+1]; | ||
47 | int essidlen; | ||
48 | int mac_enabled; | ||
49 | int was_enabled; | ||
50 | int monitor; | ||
51 | int encode_enabled; | ||
52 | int encode_restricted; | ||
53 | unsigned char encode_keys[ZD1201_NUMKEYS][ZD1201_MAXKEYLEN]; | ||
54 | int encode_keylen[ZD1201_NUMKEYS]; | ||
55 | }; | ||
56 | |||
57 | struct zd1201_frag { | ||
58 | struct hlist_node fnode; | ||
59 | int seq; | ||
60 | struct sk_buff *skb; | ||
61 | }; | ||
62 | |||
63 | #define ZD1201SIWHOSTAUTH SIOCIWFIRSTPRIV | ||
64 | #define ZD1201GIWHOSTAUTH ZD1201SIWHOSTAUTH+1 | ||
65 | #define ZD1201SIWAUTHSTA SIOCIWFIRSTPRIV+2 | ||
66 | #define ZD1201SIWMAXASSOC SIOCIWFIRSTPRIV+4 | ||
67 | #define ZD1201GIWMAXASSOC ZD1201SIWMAXASSOC+1 | ||
68 | |||
69 | #define ZD1201_FW_TIMEOUT (1000) | ||
70 | |||
71 | #define ZD1201_TX_TIMEOUT (2000) | ||
72 | |||
73 | #define ZD1201_USB_CMDREQ 0 | ||
74 | #define ZD1201_USB_RESREQ 1 | ||
75 | |||
76 | #define ZD1201_CMDCODE_INIT 0x00 | ||
77 | #define ZD1201_CMDCODE_ENABLE 0x01 | ||
78 | #define ZD1201_CMDCODE_DISABLE 0x02 | ||
79 | #define ZD1201_CMDCODE_ALLOC 0x0a | ||
80 | #define ZD1201_CMDCODE_INQUIRE 0x11 | ||
81 | #define ZD1201_CMDCODE_SETRXRID 0x17 | ||
82 | #define ZD1201_CMDCODE_ACCESS 0x21 | ||
83 | |||
84 | #define ZD1201_PACKET_EVENTSTAT 0x0 | ||
85 | #define ZD1201_PACKET_RXDATA 0x1 | ||
86 | #define ZD1201_PACKET_INQUIRE 0x2 | ||
87 | #define ZD1201_PACKET_RESOURCE 0x3 | ||
88 | |||
89 | #define ZD1201_ACCESSBIT 0x0100 | ||
90 | |||
91 | #define ZD1201_RID_CNFPORTTYPE 0xfc00 | ||
92 | #define ZD1201_RID_CNFOWNMACADDR 0xfc01 | ||
93 | #define ZD1201_RID_CNFDESIREDSSID 0xfc02 | ||
94 | #define ZD1201_RID_CNFOWNCHANNEL 0xfc03 | ||
95 | #define ZD1201_RID_CNFOWNSSID 0xfc04 | ||
96 | #define ZD1201_RID_CNFMAXDATALEN 0xfc07 | ||
97 | #define ZD1201_RID_CNFPMENABLED 0xfc09 | ||
98 | #define ZD1201_RID_CNFPMEPS 0xfc0a | ||
99 | #define ZD1201_RID_CNFMAXSLEEPDURATION 0xfc0c | ||
100 | #define ZD1201_RID_CNFDEFAULTKEYID 0xfc23 | ||
101 | #define ZD1201_RID_CNFDEFAULTKEY0 0xfc24 | ||
102 | #define ZD1201_RID_CNFDEFAULTKEY1 0xfc25 | ||
103 | #define ZD1201_RID_CNFDEFAULTKEY2 0xfc26 | ||
104 | #define ZD1201_RID_CNFDEFAULTKEY3 0xfc27 | ||
105 | #define ZD1201_RID_CNFWEBFLAGS 0xfc28 | ||
106 | #define ZD1201_RID_CNFAUTHENTICATION 0xfc2a | ||
107 | #define ZD1201_RID_CNFMAXASSOCSTATIONS 0xfc2b | ||
108 | #define ZD1201_RID_CNFHOSTAUTH 0xfc2e | ||
109 | #define ZD1201_RID_CNFGROUPADDRESS 0xfc80 | ||
110 | #define ZD1201_RID_CNFFRAGTHRESHOLD 0xfc82 | ||
111 | #define ZD1201_RID_CNFRTSTHRESHOLD 0xfc83 | ||
112 | #define ZD1201_RID_TXRATECNTL 0xfc84 | ||
113 | #define ZD1201_RID_PROMISCUOUSMODE 0xfc85 | ||
114 | #define ZD1201_RID_CNFBASICRATES 0xfcb3 | ||
115 | #define ZD1201_RID_AUTHENTICATESTA 0xfce3 | ||
116 | #define ZD1201_RID_CURRENTBSSID 0xfd42 | ||
117 | #define ZD1201_RID_COMMSQUALITY 0xfd43 | ||
118 | #define ZD1201_RID_CURRENTTXRATE 0xfd44 | ||
119 | #define ZD1201_RID_CNFMAXTXBUFFERNUMBER 0xfda0 | ||
120 | #define ZD1201_RID_CURRENTCHANNEL 0xfdc1 | ||
121 | |||
122 | #define ZD1201_INQ_SCANRESULTS 0xf101 | ||
123 | |||
124 | #define ZD1201_INF_LINKSTATUS 0xf200 | ||
125 | #define ZD1201_INF_ASSOCSTATUS 0xf201 | ||
126 | #define ZD1201_INF_AUTHREQ 0xf202 | ||
127 | |||
128 | #define ZD1201_ASSOCSTATUS_STAASSOC 0x1 | ||
129 | #define ZD1201_ASSOCSTATUS_REASSOC 0x2 | ||
130 | #define ZD1201_ASSOCSTATUS_DISASSOC 0x3 | ||
131 | #define ZD1201_ASSOCSTATUS_ASSOCFAIL 0x4 | ||
132 | #define ZD1201_ASSOCSTATUS_AUTHFAIL 0x5 | ||
133 | |||
134 | #define ZD1201_PORTTYPE_IBSS 0 | ||
135 | #define ZD1201_PORTTYPE_BSS 1 | ||
136 | #define ZD1201_PORTTYPE_WDS 2 | ||
137 | #define ZD1201_PORTTYPE_PSEUDOIBSS 3 | ||
138 | #define ZD1201_PORTTYPE_AP 6 | ||
139 | |||
140 | #define ZD1201_RATEB1 1 | ||
141 | #define ZD1201_RATEB2 2 | ||
142 | #define ZD1201_RATEB5 4 /* 5.5 really, but 5 is shorter :) */ | ||
143 | #define ZD1201_RATEB11 8 | ||
144 | |||
145 | #define ZD1201_CNFAUTHENTICATION_OPENSYSTEM 0x0001 | ||
146 | #define ZD1201_CNFAUTHENTICATION_SHAREDKEY 0x0002 | ||
147 | |||
148 | #endif /* _INCLUDE_ZD1201_H_ */ | ||
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 5c60be521561..8bd44fda5eaf 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -417,7 +417,7 @@ config USB_SERIAL_MCT_U232 | |||
417 | Magic Control Technology Corp. (U232 is one of the model numbers). | 417 | Magic Control Technology Corp. (U232 is one of the model numbers). |
418 | 418 | ||
419 | This driver also works with Sitecom U232-P25 and D-Link DU-H3SP USB | 419 | This driver also works with Sitecom U232-P25 and D-Link DU-H3SP USB |
420 | BAY devices. | 420 | BAY, Belkin F5U109, and Belkin F5U409 devices. |
421 | 421 | ||
422 | To compile this driver as a module, choose M here: the | 422 | To compile this driver as a module, choose M here: the |
423 | module will be called mct_u232. | 423 | module will be called mct_u232. |
@@ -491,16 +491,22 @@ config USB_SERIAL_XIRCOM | |||
491 | module will be called keyspan_pda. | 491 | module will be called keyspan_pda. |
492 | 492 | ||
493 | config USB_SERIAL_OPTION | 493 | config USB_SERIAL_OPTION |
494 | tristate "USB Option PCMCIA serial driver" | 494 | tristate "USB driver for GSM modems" |
495 | depends on USB_SERIAL && USB_OHCI_HCD && PCCARD | 495 | depends on USB_SERIAL |
496 | help | 496 | help |
497 | Say Y here if you want to use an Option card. This is a | 497 | Say Y here if you have an "Option" GSM PCMCIA card |
498 | GSM card, controlled by three serial ports which are connected | 498 | (or an OEM version: branded Huawei, Audiovox, or Novatel). |
499 | via an OHCI adapter located on a PC card. | 499 | |
500 | These cards feature a built-in OHCI-USB adapter and an | ||
501 | internally-connected GSM modem. The USB bus is not | ||
502 | accessible externally. | ||
500 | 503 | ||
501 | To compile this driver as a module, choose M here: the | 504 | To compile this driver as a module, choose M here: the |
502 | module will be called option. | 505 | module will be called option. |
503 | 506 | ||
507 | If this driver doesn't recognize your device, | ||
508 | it might be accessible via the FTDI_SIO driver. | ||
509 | |||
504 | config USB_SERIAL_OMNINET | 510 | config USB_SERIAL_OMNINET |
505 | tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)" | 511 | tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)" |
506 | depends on USB_SERIAL && EXPERIMENTAL | 512 | depends on USB_SERIAL && EXPERIMENTAL |
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 694b205f9b73..94b9ba0ff875 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c | |||
@@ -16,9 +16,11 @@ | |||
16 | #include "usb-serial.h" | 16 | #include "usb-serial.h" |
17 | 17 | ||
18 | static struct usb_device_id id_table [] = { | 18 | static struct usb_device_id id_table [] = { |
19 | { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ | ||
19 | { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ | 20 | { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ |
20 | { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ | 21 | { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ |
21 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ | 22 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ |
23 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ | ||
22 | { }, | 24 | { }, |
23 | }; | 25 | }; |
24 | MODULE_DEVICE_TABLE(usb, id_table); | 26 | MODULE_DEVICE_TABLE(usb, id_table); |
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 8023bb7279b1..f3404e10afb4 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
@@ -202,7 +202,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun | |||
202 | struct usb_serial *serial; | 202 | struct usb_serial *serial; |
203 | int retval = -ENODEV; | 203 | int retval = -ENODEV; |
204 | 204 | ||
205 | if (!port) | 205 | if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) |
206 | return; | 206 | return; |
207 | serial = port->serial; | 207 | serial = port->serial; |
208 | 208 | ||
@@ -213,17 +213,38 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun | |||
213 | 213 | ||
214 | if (!port->open_count) { | 214 | if (!port->open_count) { |
215 | dbg ("%s - port not opened", __FUNCTION__); | 215 | dbg ("%s - port not opened", __FUNCTION__); |
216 | goto exit; | 216 | return; |
217 | } | 217 | } |
218 | 218 | ||
219 | /* pass on to the driver specific version of this function if it is available */ | 219 | while (count) { |
220 | if (serial->type->write) | 220 | unsigned int i; |
221 | retval = serial->type->write(port, buf, count); | 221 | unsigned int lf; |
222 | else | 222 | /* search for LF so we can insert CR if necessary */ |
223 | retval = usb_serial_generic_write(port, buf, count); | 223 | for (i=0, lf=0 ; i < count ; i++) { |
224 | 224 | if (*(buf + i) == 10) { | |
225 | exit: | 225 | lf = 1; |
226 | dbg("%s - return value (if we had one): %d", __FUNCTION__, retval); | 226 | i++; |
227 | break; | ||
228 | } | ||
229 | } | ||
230 | /* pass on to the driver specific version of this function if it is available */ | ||
231 | if (serial->type->write) | ||
232 | retval = serial->type->write(port, buf, i); | ||
233 | else | ||
234 | retval = usb_serial_generic_write(port, buf, i); | ||
235 | dbg("%s - return value : %d", __FUNCTION__, retval); | ||
236 | if (lf) { | ||
237 | /* append CR after LF */ | ||
238 | unsigned char cr = 13; | ||
239 | if (serial->type->write) | ||
240 | retval = serial->type->write(port, &cr, 1); | ||
241 | else | ||
242 | retval = usb_serial_generic_write(port, &cr, 1); | ||
243 | dbg("%s - return value : %d", __FUNCTION__, retval); | ||
244 | } | ||
245 | buf += i; | ||
246 | count -= i; | ||
247 | } | ||
227 | } | 248 | } |
228 | 249 | ||
229 | static struct console usbcons = { | 250 | static struct console usbcons = { |
@@ -234,6 +255,14 @@ static struct console usbcons = { | |||
234 | .index = -1, | 255 | .index = -1, |
235 | }; | 256 | }; |
236 | 257 | ||
258 | void usb_serial_console_disconnect(struct usb_serial *serial) | ||
259 | { | ||
260 | if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) { | ||
261 | usb_serial_console_exit(); | ||
262 | usb_serial_put(serial); | ||
263 | } | ||
264 | } | ||
265 | |||
237 | void usb_serial_console_init (int serial_debug, int minor) | 266 | void usb_serial_console_init (int serial_debug, int minor) |
238 | { | 267 | { |
239 | debug = serial_debug; | 268 | debug = serial_debug; |
@@ -259,6 +288,11 @@ void usb_serial_console_init (int serial_debug, int minor) | |||
259 | 288 | ||
260 | void usb_serial_console_exit (void) | 289 | void usb_serial_console_exit (void) |
261 | { | 290 | { |
262 | unregister_console(&usbcons); | 291 | if (usbcons_info.port) { |
292 | unregister_console(&usbcons); | ||
293 | if (usbcons_info.port->open_count) | ||
294 | usbcons_info.port->open_count--; | ||
295 | usbcons_info.port = NULL; | ||
296 | } | ||
263 | } | 297 | } |
264 | 298 | ||
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index e0c2acdb3f06..f8c0cb287736 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c | |||
@@ -59,6 +59,7 @@ static struct usb_device_id id_table [] = { | |||
59 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ | 59 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ |
60 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ | 60 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ |
61 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ | 61 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ |
62 | { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ | ||
62 | { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ | 63 | { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ |
63 | { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ | 64 | { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ |
64 | { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ | 65 | { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ |
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 2357b1d102d7..1fd5c5a9f2ef 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
@@ -469,7 +469,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs | |||
469 | 469 | ||
470 | exit: | 470 | exit: |
471 | spin_unlock(&priv->lock); | 471 | spin_unlock(&priv->lock); |
472 | schedule_work(&port->work); | 472 | usb_serial_port_softint(port); |
473 | } | 473 | } |
474 | 474 | ||
475 | static int __init cyberjack_init (void) | 475 | static int __init cyberjack_init (void) |
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 7212fbe3b6f2..5de76efe1b37 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -824,7 +824,7 @@ send: | |||
824 | priv->bytes_out += count; /* do not count the line control and size bytes */ | 824 | priv->bytes_out += count; /* do not count the line control and size bytes */ |
825 | spin_unlock_irqrestore(&priv->lock, flags); | 825 | spin_unlock_irqrestore(&priv->lock, flags); |
826 | 826 | ||
827 | schedule_work(&port->work); | 827 | usb_serial_port_softint(port); |
828 | } /* cypress_send */ | 828 | } /* cypress_send */ |
829 | 829 | ||
830 | 830 | ||
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 63f7c78a1152..afca1eae5fb5 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c | |||
@@ -335,7 +335,7 @@ static void empeg_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
335 | return; | 335 | return; |
336 | } | 336 | } |
337 | 337 | ||
338 | schedule_work(&port->work); | 338 | usb_serial_port_softint(port); |
339 | } | 339 | } |
340 | 340 | ||
341 | 341 | ||
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 986d7622273d..b2bfea7c815a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -500,6 +500,7 @@ static struct usb_device_id id_table_combined [] = { | |||
500 | { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, | 500 | { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, |
501 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, | 501 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, |
502 | { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, | 502 | { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, |
503 | { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, | ||
503 | { }, /* Optional parameter entry */ | 504 | { }, /* Optional parameter entry */ |
504 | { } /* Terminating entry */ | 505 | { } /* Terminating entry */ |
505 | }; | 506 | }; |
@@ -1261,7 +1262,6 @@ static void ftdi_shutdown (struct usb_serial *serial) | |||
1261 | 1262 | ||
1262 | static int ftdi_open (struct usb_serial_port *port, struct file *filp) | 1263 | static int ftdi_open (struct usb_serial_port *port, struct file *filp) |
1263 | { /* ftdi_open */ | 1264 | { /* ftdi_open */ |
1264 | struct termios tmp_termios; | ||
1265 | struct usb_device *dev = port->serial->dev; | 1265 | struct usb_device *dev = port->serial->dev; |
1266 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1266 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1267 | unsigned long flags; | 1267 | unsigned long flags; |
@@ -1271,8 +1271,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) | |||
1271 | 1271 | ||
1272 | dbg("%s", __FUNCTION__); | 1272 | dbg("%s", __FUNCTION__); |
1273 | 1273 | ||
1274 | 1274 | if (port->tty) | |
1275 | port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1275 | port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1276 | 1276 | ||
1277 | /* No error checking for this (will get errors later anyway) */ | 1277 | /* No error checking for this (will get errors later anyway) */ |
1278 | /* See ftdi_sio.h for description of what is reset */ | 1278 | /* See ftdi_sio.h for description of what is reset */ |
@@ -1286,7 +1286,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) | |||
1286 | This is same behaviour as serial.c/rs_open() - Kuba */ | 1286 | This is same behaviour as serial.c/rs_open() - Kuba */ |
1287 | 1287 | ||
1288 | /* ftdi_set_termios will send usb control messages */ | 1288 | /* ftdi_set_termios will send usb control messages */ |
1289 | ftdi_set_termios(port, &tmp_termios); | 1289 | if (port->tty) |
1290 | ftdi_set_termios(port, NULL); | ||
1290 | 1291 | ||
1291 | /* FIXME: Flow control might be enabled, so it should be checked - | 1292 | /* FIXME: Flow control might be enabled, so it should be checked - |
1292 | we have no control of defaults! */ | 1293 | we have no control of defaults! */ |
@@ -1472,7 +1473,7 @@ static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1472 | return; | 1473 | return; |
1473 | } | 1474 | } |
1474 | 1475 | ||
1475 | schedule_work(&port->work); | 1476 | usb_serial_port_softint(port); |
1476 | } /* ftdi_write_bulk_callback */ | 1477 | } /* ftdi_write_bulk_callback */ |
1477 | 1478 | ||
1478 | 1479 | ||
@@ -1867,7 +1868,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ | |||
1867 | err("%s urb failed to set baudrate", __FUNCTION__); | 1868 | err("%s urb failed to set baudrate", __FUNCTION__); |
1868 | } | 1869 | } |
1869 | /* Ensure RTS and DTR are raised when baudrate changed from 0 */ | 1870 | /* Ensure RTS and DTR are raised when baudrate changed from 0 */ |
1870 | if ((old_termios->c_cflag & CBAUD) == B0) { | 1871 | if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) { |
1871 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 1872 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); |
1872 | } | 1873 | } |
1873 | } | 1874 | } |
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index d69a917e768f..6ab2ac845bd7 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h | |||
@@ -436,6 +436,12 @@ | |||
436 | */ | 436 | */ |
437 | #define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ | 437 | #define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ |
438 | 438 | ||
439 | /* | ||
440 | * Yost Engineering, Inc. products (www.yostengineering.com). | ||
441 | * PID 0xE050 submitted by Aaron Prose. | ||
442 | */ | ||
443 | #define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */ | ||
444 | |||
439 | /* Commands */ | 445 | /* Commands */ |
440 | #define FTDI_SIO_RESET 0 /* Reset the port */ | 446 | #define FTDI_SIO_RESET 0 /* Reset the port */ |
441 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ | 447 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ |
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 5ec9bf5bac8d..04767759cf8a 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
@@ -1012,7 +1012,7 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1012 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; | 1012 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | schedule_work(&port->work); | 1015 | usb_serial_port_softint(port); |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | 1018 | ||
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index c62cc2876519..07a478c59fb2 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -299,9 +299,7 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *re | |||
299 | return; | 299 | return; |
300 | } | 300 | } |
301 | 301 | ||
302 | usb_serial_port_softint((void *)port); | 302 | usb_serial_port_softint(port); |
303 | |||
304 | schedule_work(&port->work); | ||
305 | } | 303 | } |
306 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); | 304 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); |
307 | 305 | ||
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index b606c5968102..b85d2156dfdc 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c | |||
@@ -142,7 +142,7 @@ struct edgeport_port { | |||
142 | 142 | ||
143 | /* This structure holds all of the individual device information */ | 143 | /* This structure holds all of the individual device information */ |
144 | struct edgeport_serial { | 144 | struct edgeport_serial { |
145 | char name[MAX_NAME_LEN+1]; /* string name of this device */ | 145 | char name[MAX_NAME_LEN+2]; /* string name of this device */ |
146 | 146 | ||
147 | struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */ | 147 | struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */ |
148 | struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */ | 148 | struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */ |
@@ -270,7 +270,7 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial); | |||
270 | static void get_boot_desc (struct edgeport_serial *edge_serial); | 270 | static void get_boot_desc (struct edgeport_serial *edge_serial); |
271 | static void load_application_firmware (struct edgeport_serial *edge_serial); | 271 | static void load_application_firmware (struct edgeport_serial *edge_serial); |
272 | 272 | ||
273 | static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size); | 273 | static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size); |
274 | 274 | ||
275 | 275 | ||
276 | // ************************************************************************ | 276 | // ************************************************************************ |
@@ -373,7 +373,7 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial) | |||
373 | * Get string descriptor from device * | 373 | * Get string descriptor from device * |
374 | * * | 374 | * * |
375 | ************************************************************************/ | 375 | ************************************************************************/ |
376 | static int get_string (struct usb_device *dev, int Id, char *string) | 376 | static int get_string (struct usb_device *dev, int Id, char *string, int buflen) |
377 | { | 377 | { |
378 | struct usb_string_descriptor StringDesc; | 378 | struct usb_string_descriptor StringDesc; |
379 | struct usb_string_descriptor *pStringDesc; | 379 | struct usb_string_descriptor *pStringDesc; |
@@ -395,7 +395,7 @@ static int get_string (struct usb_device *dev, int Id, char *string) | |||
395 | return 0; | 395 | return 0; |
396 | } | 396 | } |
397 | 397 | ||
398 | unicode_to_ascii(string, pStringDesc->wData, pStringDesc->bLength/2-1); | 398 | unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2); |
399 | 399 | ||
400 | kfree(pStringDesc); | 400 | kfree(pStringDesc); |
401 | return strlen(string); | 401 | return strlen(string); |
@@ -2564,16 +2564,20 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio | |||
2564 | * ASCII range, but it's only for debugging... | 2564 | * ASCII range, but it's only for debugging... |
2565 | * NOTE: expects the unicode in LE format | 2565 | * NOTE: expects the unicode in LE format |
2566 | ****************************************************************************/ | 2566 | ****************************************************************************/ |
2567 | static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size) | 2567 | static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size) |
2568 | { | 2568 | { |
2569 | int i; | 2569 | int i; |
2570 | 2570 | ||
2571 | if (unicode_size <= 0) | 2571 | if (buflen <= 0) /* never happens, but... */ |
2572 | return; | 2572 | return; |
2573 | --buflen; /* space for nul */ | ||
2573 | 2574 | ||
2574 | for (i = 0; i < unicode_size; ++i) | 2575 | for (i = 0; i < unicode_size; i++) { |
2576 | if (i >= buflen) | ||
2577 | break; | ||
2575 | string[i] = (char)(le16_to_cpu(unicode[i])); | 2578 | string[i] = (char)(le16_to_cpu(unicode[i])); |
2576 | string[unicode_size] = 0x00; | 2579 | } |
2580 | string[i] = 0x00; | ||
2577 | } | 2581 | } |
2578 | 2582 | ||
2579 | 2583 | ||
@@ -2603,11 +2607,17 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial) | |||
2603 | dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev); | 2607 | dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev); |
2604 | dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts); | 2608 | dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts); |
2605 | dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); | 2609 | dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); |
2606 | unicode_to_ascii (string, edge_serial->manuf_descriptor.SerialNumber, edge_serial->manuf_descriptor.SerNumLength/2-1); | 2610 | unicode_to_ascii(string, sizeof(string), |
2611 | edge_serial->manuf_descriptor.SerialNumber, | ||
2612 | edge_serial->manuf_descriptor.SerNumLength/2); | ||
2607 | dbg(" SerialNumber: %s", string); | 2613 | dbg(" SerialNumber: %s", string); |
2608 | unicode_to_ascii (string, edge_serial->manuf_descriptor.AssemblyNumber, edge_serial->manuf_descriptor.AssemblyNumLength/2-1); | 2614 | unicode_to_ascii(string, sizeof(string), |
2615 | edge_serial->manuf_descriptor.AssemblyNumber, | ||
2616 | edge_serial->manuf_descriptor.AssemblyNumLength/2); | ||
2609 | dbg(" AssemblyNumber: %s", string); | 2617 | dbg(" AssemblyNumber: %s", string); |
2610 | unicode_to_ascii (string, edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2-1); | 2618 | unicode_to_ascii(string, sizeof(string), |
2619 | edge_serial->manuf_descriptor.OemAssyNumber, | ||
2620 | edge_serial->manuf_descriptor.OemAssyNumLength/2); | ||
2611 | dbg(" OemAssyNumber: %s", string); | 2621 | dbg(" OemAssyNumber: %s", string); |
2612 | dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType); | 2622 | dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType); |
2613 | dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid); | 2623 | dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid); |
@@ -2720,7 +2730,7 @@ static int edge_startup (struct usb_serial *serial) | |||
2720 | struct edgeport_serial *edge_serial; | 2730 | struct edgeport_serial *edge_serial; |
2721 | struct edgeport_port *edge_port; | 2731 | struct edgeport_port *edge_port; |
2722 | struct usb_device *dev; | 2732 | struct usb_device *dev; |
2723 | int i; | 2733 | int i, j; |
2724 | 2734 | ||
2725 | dev = serial->dev; | 2735 | dev = serial->dev; |
2726 | 2736 | ||
@@ -2735,11 +2745,11 @@ static int edge_startup (struct usb_serial *serial) | |||
2735 | usb_set_serial_data(serial, edge_serial); | 2745 | usb_set_serial_data(serial, edge_serial); |
2736 | 2746 | ||
2737 | /* get the name for the device from the device */ | 2747 | /* get the name for the device from the device */ |
2738 | if ( (i = get_string(dev, dev->descriptor.iManufacturer, &edge_serial->name[0])) != 0) { | 2748 | i = get_string(dev, dev->descriptor.iManufacturer, |
2739 | edge_serial->name[i-1] = ' '; | 2749 | &edge_serial->name[0], MAX_NAME_LEN+1); |
2740 | } | 2750 | edge_serial->name[i++] = ' '; |
2741 | 2751 | get_string(dev, dev->descriptor.iProduct, | |
2742 | get_string(dev, dev->descriptor.iProduct, &edge_serial->name[i]); | 2752 | &edge_serial->name[i], MAX_NAME_LEN+2 - i); |
2743 | 2753 | ||
2744 | dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); | 2754 | dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); |
2745 | 2755 | ||
@@ -2784,6 +2794,10 @@ static int edge_startup (struct usb_serial *serial) | |||
2784 | edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); | 2794 | edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); |
2785 | if (edge_port == NULL) { | 2795 | if (edge_port == NULL) { |
2786 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); | 2796 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); |
2797 | for (j = 0; j < i; ++j) { | ||
2798 | kfree (usb_get_serial_port_data(serial->port[j])); | ||
2799 | usb_set_serial_port_data(serial->port[j], NULL); | ||
2800 | } | ||
2787 | usb_set_serial_data(serial, NULL); | 2801 | usb_set_serial_data(serial, NULL); |
2788 | kfree(edge_serial); | 2802 | kfree(edge_serial); |
2789 | return -ENOMEM; | 2803 | return -ENOMEM; |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 9a5c97989562..9da6d2a8f2b0 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -870,7 +870,7 @@ static void ipaq_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
870 | spin_unlock_irqrestore(&write_list_lock, flags); | 870 | spin_unlock_irqrestore(&write_list_lock, flags); |
871 | } | 871 | } |
872 | 872 | ||
873 | schedule_work(&port->work); | 873 | usb_serial_port_softint(port); |
874 | } | 874 | } |
875 | 875 | ||
876 | static int ipaq_write_room(struct usb_serial_port *port) | 876 | static int ipaq_write_room(struct usb_serial_port *port) |
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index e760a70242c1..a4a0bfeaab00 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c | |||
@@ -376,7 +376,7 @@ static void ipw_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
376 | if (urb->status) | 376 | if (urb->status) |
377 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 377 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
378 | 378 | ||
379 | schedule_work(&port->work); | 379 | usb_serial_port_softint(port); |
380 | } | 380 | } |
381 | 381 | ||
382 | static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count) | 382 | static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count) |
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 426182ddc42a..9432c7302275 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
@@ -408,7 +408,7 @@ static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
408 | urb->actual_length, | 408 | urb->actual_length, |
409 | urb->transfer_buffer); | 409 | urb->transfer_buffer); |
410 | 410 | ||
411 | schedule_work(&port->work); | 411 | usb_serial_port_softint(port); |
412 | } | 412 | } |
413 | 413 | ||
414 | static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | 414 | static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs) |
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 052b735c4fbd..2cf6ade704e4 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
@@ -481,7 +481,7 @@ static void usa2x_outdat_callback(struct urb *urb, struct pt_regs *regs) | |||
481 | dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); | 481 | dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); |
482 | 482 | ||
483 | if (port->open_count) | 483 | if (port->open_count) |
484 | schedule_work(&port->work); | 484 | usb_serial_port_softint(port); |
485 | } | 485 | } |
486 | 486 | ||
487 | static void usa26_inack_callback(struct urb *urb, struct pt_regs *regs) | 487 | static void usa26_inack_callback(struct urb *urb, struct pt_regs *regs) |
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 78335a5f7743..65d79f630fa4 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c | |||
@@ -569,8 +569,7 @@ static void klsi_105_write_bulk_callback ( struct urb *urb, struct pt_regs *regs | |||
569 | return; | 569 | return; |
570 | } | 570 | } |
571 | 571 | ||
572 | /* from generic_write_bulk_callback */ | 572 | usb_serial_port_softint(port); |
573 | schedule_work(&port->work); | ||
574 | } /* klsi_105_write_bulk_completion_callback */ | 573 | } /* klsi_105_write_bulk_completion_callback */ |
575 | 574 | ||
576 | 575 | ||
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 238033a87092..6dcdb5f598b8 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
@@ -320,7 +320,7 @@ static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
320 | return; | 320 | return; |
321 | } | 321 | } |
322 | 322 | ||
323 | schedule_work(&port->work); | 323 | usb_serial_port_softint(port); |
324 | } | 324 | } |
325 | 325 | ||
326 | 326 | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5cf2b80add7a..b0861b61bba7 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Option Card (PCMCIA to) USB to Serial Driver | 2 | USB Driver for GSM modems |
3 | 3 | ||
4 | Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de> | 4 | Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de> |
5 | 5 | ||
@@ -28,15 +28,34 @@ | |||
28 | 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard | 28 | 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard |
29 | 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes | 29 | 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes |
30 | wants to send >2000 bytes. | 30 | wants to send >2000 bytes. |
31 | 2006-04-10 v0.4.2 fixed two array overrun errors :-/ | 31 | 2006-04-10 v0.5 fixed two array overrun errors :-/ |
32 | 2006-04-21 v0.5.1 added support for Sierra Wireless MC8755 | ||
33 | 2006-05-15 v0.6 re-enable multi-port support | ||
34 | 2006-06-01 v0.6.1 add COBRA | ||
35 | 2006-06-01 v0.6.2 add backwards-compatibility stuff | ||
36 | 2006-06-01 v0.6.3 add Novatel Wireless | ||
37 | 2006-06-01 v0.7 Option => GSM | ||
32 | 38 | ||
33 | Work sponsored by: Sigos GmbH, Germany <info@sigos.de> | 39 | Work sponsored by: Sigos GmbH, Germany <info@sigos.de> |
34 | 40 | ||
41 | This driver exists because the "normal" serial driver doesn't work too well | ||
42 | with GSM modems. Issues: | ||
43 | - data loss -- one single Receive URB is not nearly enough | ||
44 | - nonstandard flow (Option devices) and multiplex (Sierra) control | ||
45 | - controlling the baud rate doesn't make sense | ||
46 | |||
47 | This driver is named "option" because the most common device it's | ||
48 | used for is a PC-Card (with an internal OHCI-USB interface, behind | ||
49 | which the GSM interface sits), made by Option Inc. | ||
50 | |||
51 | Some of the "one port" devices actually exhibit multiple USB instances | ||
52 | on the USB bus. This is not a bug, these ports are used for different | ||
53 | device features. | ||
35 | */ | 54 | */ |
36 | 55 | ||
37 | #define DRIVER_VERSION "v0.4" | 56 | #define DRIVER_VERSION "v0.7.0" |
38 | #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" | 57 | #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" |
39 | #define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver" | 58 | #define DRIVER_DESC "USB Driver for GSM modems" |
40 | 59 | ||
41 | #include <linux/config.h> | 60 | #include <linux/config.h> |
42 | #include <linux/kernel.h> | 61 | #include <linux/kernel.h> |
@@ -74,22 +93,45 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file, | |||
74 | static int option_send_setup(struct usb_serial_port *port); | 93 | static int option_send_setup(struct usb_serial_port *port); |
75 | 94 | ||
76 | /* Vendor and product IDs */ | 95 | /* Vendor and product IDs */ |
77 | #define OPTION_VENDOR_ID 0x0AF0 | 96 | #define OPTION_VENDOR_ID 0x0AF0 |
78 | #define HUAWEI_VENDOR_ID 0x12D1 | 97 | #define HUAWEI_VENDOR_ID 0x12D1 |
79 | #define AUDIOVOX_VENDOR_ID 0x0F3D | 98 | #define AUDIOVOX_VENDOR_ID 0x0F3D |
80 | 99 | #define SIERRAWIRELESS_VENDOR_ID 0x1199 | |
81 | #define OPTION_PRODUCT_OLD 0x5000 | 100 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 |
82 | #define OPTION_PRODUCT_FUSION 0x6000 | 101 | |
83 | #define OPTION_PRODUCT_FUSION2 0x6300 | 102 | #define OPTION_PRODUCT_OLD 0x5000 |
84 | #define HUAWEI_PRODUCT_E600 0x1001 | 103 | #define OPTION_PRODUCT_FUSION 0x6000 |
85 | #define AUDIOVOX_PRODUCT_AIRCARD 0x0112 | 104 | #define OPTION_PRODUCT_FUSION2 0x6300 |
105 | #define OPTION_PRODUCT_COBRA 0x6500 | ||
106 | #define HUAWEI_PRODUCT_E600 0x1001 | ||
107 | #define AUDIOVOX_PRODUCT_AIRCARD 0x0112 | ||
108 | #define SIERRAWIRELESS_PRODUCT_MC8755 0x6802 | ||
109 | #define NOVATELWIRELESS_PRODUCT_U740 0x1400 | ||
86 | 110 | ||
87 | static struct usb_device_id option_ids[] = { | 111 | static struct usb_device_id option_ids[] = { |
88 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, | 112 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, |
89 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, | 113 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, |
90 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, | 114 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, |
115 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, | ||
91 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, | 116 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, |
92 | { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, | 117 | { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, |
118 | { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, | ||
119 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, | ||
120 | { } /* Terminating entry */ | ||
121 | }; | ||
122 | |||
123 | static struct usb_device_id option_ids1[] = { | ||
124 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, | ||
125 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, | ||
126 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, | ||
127 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, | ||
128 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, | ||
129 | { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, | ||
130 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, | ||
131 | { } /* Terminating entry */ | ||
132 | }; | ||
133 | static struct usb_device_id option_ids3[] = { | ||
134 | { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, | ||
93 | { } /* Terminating entry */ | 135 | { } /* Terminating entry */ |
94 | }; | 136 | }; |
95 | 137 | ||
@@ -111,12 +153,39 @@ static struct usb_serial_driver option_3port_device = { | |||
111 | .owner = THIS_MODULE, | 153 | .owner = THIS_MODULE, |
112 | .name = "option", | 154 | .name = "option", |
113 | }, | 155 | }, |
114 | .description = "Option 3G data card", | 156 | .description = "GSM modem (3-port)", |
115 | .id_table = option_ids, | 157 | .id_table = option_ids3, |
116 | .num_interrupt_in = NUM_DONT_CARE, | 158 | .num_interrupt_in = NUM_DONT_CARE, |
117 | .num_bulk_in = NUM_DONT_CARE, | 159 | .num_bulk_in = NUM_DONT_CARE, |
118 | .num_bulk_out = NUM_DONT_CARE, | 160 | .num_bulk_out = NUM_DONT_CARE, |
119 | .num_ports = 1, /* 3, but the card reports its ports separately */ | 161 | .num_ports = 3, |
162 | .open = option_open, | ||
163 | .close = option_close, | ||
164 | .write = option_write, | ||
165 | .write_room = option_write_room, | ||
166 | .chars_in_buffer = option_chars_in_buffer, | ||
167 | .throttle = option_rx_throttle, | ||
168 | .unthrottle = option_rx_unthrottle, | ||
169 | .set_termios = option_set_termios, | ||
170 | .break_ctl = option_break_ctl, | ||
171 | .tiocmget = option_tiocmget, | ||
172 | .tiocmset = option_tiocmset, | ||
173 | .attach = option_startup, | ||
174 | .shutdown = option_shutdown, | ||
175 | .read_int_callback = option_instat_callback, | ||
176 | }; | ||
177 | |||
178 | static struct usb_serial_driver option_1port_device = { | ||
179 | .driver = { | ||
180 | .owner = THIS_MODULE, | ||
181 | .name = "option", | ||
182 | }, | ||
183 | .description = "GSM modem (1-port)", | ||
184 | .id_table = option_ids1, | ||
185 | .num_interrupt_in = NUM_DONT_CARE, | ||
186 | .num_bulk_in = NUM_DONT_CARE, | ||
187 | .num_bulk_out = NUM_DONT_CARE, | ||
188 | .num_ports = 1, | ||
120 | .open = option_open, | 189 | .open = option_open, |
121 | .close = option_close, | 190 | .close = option_close, |
122 | .write = option_write, | 191 | .write = option_write, |
@@ -170,6 +239,9 @@ struct option_port_private { | |||
170 | static int __init option_init(void) | 239 | static int __init option_init(void) |
171 | { | 240 | { |
172 | int retval; | 241 | int retval; |
242 | retval = usb_serial_register(&option_1port_device); | ||
243 | if (retval) | ||
244 | goto failed_1port_device_register; | ||
173 | retval = usb_serial_register(&option_3port_device); | 245 | retval = usb_serial_register(&option_3port_device); |
174 | if (retval) | 246 | if (retval) |
175 | goto failed_3port_device_register; | 247 | goto failed_3port_device_register; |
@@ -184,6 +256,8 @@ static int __init option_init(void) | |||
184 | failed_driver_register: | 256 | failed_driver_register: |
185 | usb_serial_deregister (&option_3port_device); | 257 | usb_serial_deregister (&option_3port_device); |
186 | failed_3port_device_register: | 258 | failed_3port_device_register: |
259 | usb_serial_deregister (&option_1port_device); | ||
260 | failed_1port_device_register: | ||
187 | return retval; | 261 | return retval; |
188 | } | 262 | } |
189 | 263 | ||
@@ -191,6 +265,7 @@ static void __exit option_exit(void) | |||
191 | { | 265 | { |
192 | usb_deregister (&option_driver); | 266 | usb_deregister (&option_driver); |
193 | usb_serial_deregister (&option_3port_device); | 267 | usb_serial_deregister (&option_3port_device); |
268 | usb_serial_deregister (&option_1port_device); | ||
194 | } | 269 | } |
195 | 270 | ||
196 | module_init(option_init); | 271 | module_init(option_init); |
@@ -365,8 +440,7 @@ static void option_outdat_callback(struct urb *urb, struct pt_regs *regs) | |||
365 | 440 | ||
366 | port = (struct usb_serial_port *) urb->context; | 441 | port = (struct usb_serial_port *) urb->context; |
367 | 442 | ||
368 | if (port->open_count) | 443 | usb_serial_port_softint(port); |
369 | schedule_work(&port->work); | ||
370 | } | 444 | } |
371 | 445 | ||
372 | static void option_instat_callback(struct urb *urb, struct pt_regs *regs) | 446 | static void option_instat_callback(struct urb *urb, struct pt_regs *regs) |
@@ -573,27 +647,30 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint, | |||
573 | /* Setup urbs */ | 647 | /* Setup urbs */ |
574 | static void option_setup_urbs(struct usb_serial *serial) | 648 | static void option_setup_urbs(struct usb_serial *serial) |
575 | { | 649 | { |
576 | int j; | 650 | int i,j; |
577 | struct usb_serial_port *port; | 651 | struct usb_serial_port *port; |
578 | struct option_port_private *portdata; | 652 | struct option_port_private *portdata; |
579 | 653 | ||
580 | dbg("%s", __FUNCTION__); | 654 | dbg("%s", __FUNCTION__); |
581 | 655 | ||
582 | port = serial->port[0]; | 656 | |
583 | portdata = usb_get_serial_port_data(port); | 657 | for (i = 0; i < serial->num_ports; i++) { |
658 | port = serial->port[i]; | ||
659 | portdata = usb_get_serial_port_data(port); | ||
584 | 660 | ||
585 | /* Do indat endpoints first */ | 661 | /* Do indat endpoints first */ |
586 | for (j = 0; j < N_IN_URB; ++j) { | 662 | for (j = 0; j < N_IN_URB; ++j) { |
587 | portdata->in_urbs[j] = option_setup_urb (serial, | 663 | portdata->in_urbs[j] = option_setup_urb (serial, |
588 | port->bulk_in_endpointAddress, USB_DIR_IN, port, | 664 | port->bulk_in_endpointAddress, USB_DIR_IN, port, |
589 | portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); | 665 | portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); |
590 | } | 666 | } |
591 | 667 | ||
592 | /* outdat endpoints */ | 668 | /* outdat endpoints */ |
593 | for (j = 0; j < N_OUT_URB; ++j) { | 669 | for (j = 0; j < N_OUT_URB; ++j) { |
594 | portdata->out_urbs[j] = option_setup_urb (serial, | 670 | portdata->out_urbs[j] = option_setup_urb (serial, |
595 | port->bulk_out_endpointAddress, USB_DIR_OUT, port, | 671 | port->bulk_out_endpointAddress, USB_DIR_OUT, port, |
596 | portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); | 672 | portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); |
673 | } | ||
597 | } | 674 | } |
598 | } | 675 | } |
599 | 676 | ||
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index c96714bb1cb8..d88704387202 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -314,7 +314,7 @@ static void pl2303_send(struct usb_serial_port *port) | |||
314 | // TODO: reschedule pl2303_send | 314 | // TODO: reschedule pl2303_send |
315 | } | 315 | } |
316 | 316 | ||
317 | schedule_work(&port->work); | 317 | usb_serial_port_softint(port); |
318 | } | 318 | } |
319 | 319 | ||
320 | static int pl2303_write_room(struct usb_serial_port *port) | 320 | static int pl2303_write_room(struct usb_serial_port *port) |
@@ -600,7 +600,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp) | |||
600 | unsigned int c_cflag; | 600 | unsigned int c_cflag; |
601 | int bps; | 601 | int bps; |
602 | long timeout; | 602 | long timeout; |
603 | wait_queue_t wait; \ | 603 | wait_queue_t wait; |
604 | 604 | ||
605 | dbg("%s - port %d", __FUNCTION__, port->number); | 605 | dbg("%s - port %d", __FUNCTION__, port->number); |
606 | 606 | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 9c36f0ece20f..a30135c7cfe6 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -162,12 +162,19 @@ static void destroy_serial(struct kref *kref) | |||
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | flush_scheduled_work(); /* port->work */ | ||
166 | |||
165 | usb_put_dev(serial->dev); | 167 | usb_put_dev(serial->dev); |
166 | 168 | ||
167 | /* free up any memory that we allocated */ | 169 | /* free up any memory that we allocated */ |
168 | kfree (serial); | 170 | kfree (serial); |
169 | } | 171 | } |
170 | 172 | ||
173 | void usb_serial_put(struct usb_serial *serial) | ||
174 | { | ||
175 | kref_put(&serial->kref, destroy_serial); | ||
176 | } | ||
177 | |||
171 | /***************************************************************************** | 178 | /***************************************************************************** |
172 | * Driver tty interface functions | 179 | * Driver tty interface functions |
173 | *****************************************************************************/ | 180 | *****************************************************************************/ |
@@ -201,12 +208,12 @@ static int serial_open (struct tty_struct *tty, struct file * filp) | |||
201 | 208 | ||
202 | ++port->open_count; | 209 | ++port->open_count; |
203 | 210 | ||
204 | if (port->open_count == 1) { | 211 | /* set up our port structure making the tty driver |
212 | * remember our port object, and us it */ | ||
213 | tty->driver_data = port; | ||
214 | port->tty = tty; | ||
205 | 215 | ||
206 | /* set up our port structure making the tty driver | 216 | if (port->open_count == 1) { |
207 | * remember our port object, and us it */ | ||
208 | tty->driver_data = port; | ||
209 | port->tty = tty; | ||
210 | 217 | ||
211 | /* lock this module before we call it | 218 | /* lock this module before we call it |
212 | * this may fail, which means we must bail out, | 219 | * this may fail, which means we must bail out, |
@@ -230,9 +237,11 @@ bailout_module_put: | |||
230 | module_put(serial->type->driver.owner); | 237 | module_put(serial->type->driver.owner); |
231 | bailout_mutex_unlock: | 238 | bailout_mutex_unlock: |
232 | port->open_count = 0; | 239 | port->open_count = 0; |
240 | tty->driver_data = NULL; | ||
241 | port->tty = NULL; | ||
233 | mutex_unlock(&port->mutex); | 242 | mutex_unlock(&port->mutex); |
234 | bailout_kref_put: | 243 | bailout_kref_put: |
235 | kref_put(&serial->kref, destroy_serial); | 244 | usb_serial_put(serial); |
236 | return retval; | 245 | return retval; |
237 | } | 246 | } |
238 | 247 | ||
@@ -268,7 +277,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp) | |||
268 | } | 277 | } |
269 | 278 | ||
270 | mutex_unlock(&port->mutex); | 279 | mutex_unlock(&port->mutex); |
271 | kref_put(&port->serial->kref, destroy_serial); | 280 | usb_serial_put(port->serial); |
272 | } | 281 | } |
273 | 282 | ||
274 | static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) | 283 | static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) |
@@ -276,7 +285,7 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int | |||
276 | struct usb_serial_port *port = tty->driver_data; | 285 | struct usb_serial_port *port = tty->driver_data; |
277 | int retval = -EINVAL; | 286 | int retval = -EINVAL; |
278 | 287 | ||
279 | if (!port) | 288 | if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) |
280 | goto exit; | 289 | goto exit; |
281 | 290 | ||
282 | dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); | 291 | dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); |
@@ -296,7 +305,7 @@ exit: | |||
296 | static int serial_write_room (struct tty_struct *tty) | 305 | static int serial_write_room (struct tty_struct *tty) |
297 | { | 306 | { |
298 | struct usb_serial_port *port = tty->driver_data; | 307 | struct usb_serial_port *port = tty->driver_data; |
299 | int retval = -EINVAL; | 308 | int retval = -ENODEV; |
300 | 309 | ||
301 | if (!port) | 310 | if (!port) |
302 | goto exit; | 311 | goto exit; |
@@ -318,7 +327,7 @@ exit: | |||
318 | static int serial_chars_in_buffer (struct tty_struct *tty) | 327 | static int serial_chars_in_buffer (struct tty_struct *tty) |
319 | { | 328 | { |
320 | struct usb_serial_port *port = tty->driver_data; | 329 | struct usb_serial_port *port = tty->driver_data; |
321 | int retval = -EINVAL; | 330 | int retval = -ENODEV; |
322 | 331 | ||
323 | if (!port) | 332 | if (!port) |
324 | goto exit; | 333 | goto exit; |
@@ -473,7 +482,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int | |||
473 | begin += length; | 482 | begin += length; |
474 | length = 0; | 483 | length = 0; |
475 | } | 484 | } |
476 | kref_put(&serial->kref, destroy_serial); | 485 | usb_serial_put(serial); |
477 | } | 486 | } |
478 | *eof = 1; | 487 | *eof = 1; |
479 | done: | 488 | done: |
@@ -488,19 +497,18 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file) | |||
488 | struct usb_serial_port *port = tty->driver_data; | 497 | struct usb_serial_port *port = tty->driver_data; |
489 | 498 | ||
490 | if (!port) | 499 | if (!port) |
491 | goto exit; | 500 | return -ENODEV; |
492 | 501 | ||
493 | dbg("%s - port %d", __FUNCTION__, port->number); | 502 | dbg("%s - port %d", __FUNCTION__, port->number); |
494 | 503 | ||
495 | if (!port->open_count) { | 504 | if (!port->open_count) { |
496 | dbg("%s - port not open", __FUNCTION__); | 505 | dbg("%s - port not open", __FUNCTION__); |
497 | goto exit; | 506 | return -ENODEV; |
498 | } | 507 | } |
499 | 508 | ||
500 | if (port->serial->type->tiocmget) | 509 | if (port->serial->type->tiocmget) |
501 | return port->serial->type->tiocmget(port, file); | 510 | return port->serial->type->tiocmget(port, file); |
502 | 511 | ||
503 | exit: | ||
504 | return -EINVAL; | 512 | return -EINVAL; |
505 | } | 513 | } |
506 | 514 | ||
@@ -510,23 +518,32 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file, | |||
510 | struct usb_serial_port *port = tty->driver_data; | 518 | struct usb_serial_port *port = tty->driver_data; |
511 | 519 | ||
512 | if (!port) | 520 | if (!port) |
513 | goto exit; | 521 | return -ENODEV; |
514 | 522 | ||
515 | dbg("%s - port %d", __FUNCTION__, port->number); | 523 | dbg("%s - port %d", __FUNCTION__, port->number); |
516 | 524 | ||
517 | if (!port->open_count) { | 525 | if (!port->open_count) { |
518 | dbg("%s - port not open", __FUNCTION__); | 526 | dbg("%s - port not open", __FUNCTION__); |
519 | goto exit; | 527 | return -ENODEV; |
520 | } | 528 | } |
521 | 529 | ||
522 | if (port->serial->type->tiocmset) | 530 | if (port->serial->type->tiocmset) |
523 | return port->serial->type->tiocmset(port, file, set, clear); | 531 | return port->serial->type->tiocmset(port, file, set, clear); |
524 | 532 | ||
525 | exit: | ||
526 | return -EINVAL; | 533 | return -EINVAL; |
527 | } | 534 | } |
528 | 535 | ||
529 | void usb_serial_port_softint(void *private) | 536 | /* |
537 | * We would be calling tty_wakeup here, but unfortunately some line | ||
538 | * disciplines have an annoying habit of calling tty->write from | ||
539 | * the write wakeup callback (e.g. n_hdlc.c). | ||
540 | */ | ||
541 | void usb_serial_port_softint(struct usb_serial_port *port) | ||
542 | { | ||
543 | schedule_work(&port->work); | ||
544 | } | ||
545 | |||
546 | static void usb_serial_port_work(void *private) | ||
530 | { | 547 | { |
531 | struct usb_serial_port *port = private; | 548 | struct usb_serial_port *port = private; |
532 | struct tty_struct *tty; | 549 | struct tty_struct *tty; |
@@ -789,7 +806,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
789 | port->serial = serial; | 806 | port->serial = serial; |
790 | spin_lock_init(&port->lock); | 807 | spin_lock_init(&port->lock); |
791 | mutex_init(&port->mutex); | 808 | mutex_init(&port->mutex); |
792 | INIT_WORK(&port->work, usb_serial_port_softint, port); | 809 | INIT_WORK(&port->work, usb_serial_port_work, port); |
793 | serial->port[i] = port; | 810 | serial->port[i] = port; |
794 | } | 811 | } |
795 | 812 | ||
@@ -985,6 +1002,7 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
985 | struct device *dev = &interface->dev; | 1002 | struct device *dev = &interface->dev; |
986 | struct usb_serial_port *port; | 1003 | struct usb_serial_port *port; |
987 | 1004 | ||
1005 | usb_serial_console_disconnect(serial); | ||
988 | dbg ("%s", __FUNCTION__); | 1006 | dbg ("%s", __FUNCTION__); |
989 | 1007 | ||
990 | usb_set_intfdata (interface, NULL); | 1008 | usb_set_intfdata (interface, NULL); |
@@ -996,7 +1014,7 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
996 | } | 1014 | } |
997 | /* let the last holder of this object | 1015 | /* let the last holder of this object |
998 | * cause it to be cleaned up */ | 1016 | * cause it to be cleaned up */ |
999 | kref_put(&serial->kref, destroy_serial); | 1017 | usb_serial_put(serial); |
1000 | } | 1018 | } |
1001 | dev_info(dev, "device disconnected\n"); | 1019 | dev_info(dev, "device disconnected\n"); |
1002 | } | 1020 | } |
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index dc89d8710460..d53ea9b11e81 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h | |||
@@ -236,7 +236,7 @@ struct usb_serial_driver { | |||
236 | 236 | ||
237 | extern int usb_serial_register(struct usb_serial_driver *driver); | 237 | extern int usb_serial_register(struct usb_serial_driver *driver); |
238 | extern void usb_serial_deregister(struct usb_serial_driver *driver); | 238 | extern void usb_serial_deregister(struct usb_serial_driver *driver); |
239 | extern void usb_serial_port_softint(void *private); | 239 | extern void usb_serial_port_softint(struct usb_serial_port *port); |
240 | 240 | ||
241 | extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); | 241 | extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); |
242 | extern void usb_serial_disconnect(struct usb_interface *iface); | 242 | extern void usb_serial_disconnect(struct usb_interface *iface); |
@@ -248,13 +248,16 @@ extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit); | |||
248 | #ifdef CONFIG_USB_SERIAL_CONSOLE | 248 | #ifdef CONFIG_USB_SERIAL_CONSOLE |
249 | extern void usb_serial_console_init (int debug, int minor); | 249 | extern void usb_serial_console_init (int debug, int minor); |
250 | extern void usb_serial_console_exit (void); | 250 | extern void usb_serial_console_exit (void); |
251 | extern void usb_serial_console_disconnect(struct usb_serial *serial); | ||
251 | #else | 252 | #else |
252 | static inline void usb_serial_console_init (int debug, int minor) { } | 253 | static inline void usb_serial_console_init (int debug, int minor) { } |
253 | static inline void usb_serial_console_exit (void) { } | 254 | static inline void usb_serial_console_exit (void) { } |
255 | static inline void usb_serial_console_disconnect(struct usb_serial *serial) {} | ||
254 | #endif | 256 | #endif |
255 | 257 | ||
256 | /* Functions needed by other parts of the usbserial core */ | 258 | /* Functions needed by other parts of the usbserial core */ |
257 | extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); | 259 | extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); |
260 | extern void usb_serial_put(struct usb_serial *serial); | ||
258 | extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); | 261 | extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); |
259 | extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); | 262 | extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); |
260 | extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); | 263 | extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); |
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index f5c3841d4843..9e89b8d54f72 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c | |||
@@ -480,7 +480,7 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
480 | --priv->outstanding_urbs; | 480 | --priv->outstanding_urbs; |
481 | spin_unlock_irqrestore(&priv->lock, flags); | 481 | spin_unlock_irqrestore(&priv->lock, flags); |
482 | 482 | ||
483 | schedule_work(&port->work); | 483 | usb_serial_port_softint(port); |
484 | } | 484 | } |
485 | 485 | ||
486 | 486 | ||
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index f806553cd9a4..5b06fa366098 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c | |||
@@ -388,7 +388,7 @@ static int whiteheat_attach (struct usb_serial *serial) | |||
388 | if (ret) { | 388 | if (ret) { |
389 | err("%s: Couldn't send command [%d]", serial->type->description, ret); | 389 | err("%s: Couldn't send command [%d]", serial->type->description, ret); |
390 | goto no_firmware; | 390 | goto no_firmware; |
391 | } else if (alen != sizeof(command)) { | 391 | } else if (alen != 2) { |
392 | err("%s: Send command incomplete [%d]", serial->type->description, alen); | 392 | err("%s: Send command incomplete [%d]", serial->type->description, alen); |
393 | goto no_firmware; | 393 | goto no_firmware; |
394 | } | 394 | } |
@@ -400,7 +400,7 @@ static int whiteheat_attach (struct usb_serial *serial) | |||
400 | if (ret) { | 400 | if (ret) { |
401 | err("%s: Couldn't get results [%d]", serial->type->description, ret); | 401 | err("%s: Couldn't get results [%d]", serial->type->description, ret); |
402 | goto no_firmware; | 402 | goto no_firmware; |
403 | } else if (alen != sizeof(result)) { | 403 | } else if (alen != sizeof(*hw_info) + 1) { |
404 | err("%s: Get results incomplete [%d]", serial->type->description, alen); | 404 | err("%s: Get results incomplete [%d]", serial->type->description, alen); |
405 | goto no_firmware; | 405 | goto no_firmware; |
406 | } else if (result[0] != command[0]) { | 406 | } else if (result[0] != command[0]) { |
@@ -1089,9 +1089,7 @@ static void whiteheat_write_callback(struct urb *urb, struct pt_regs *regs) | |||
1089 | return; | 1089 | return; |
1090 | } | 1090 | } |
1091 | 1091 | ||
1092 | usb_serial_port_softint((void *)port); | 1092 | usb_serial_port_softint(port); |
1093 | |||
1094 | schedule_work(&port->work); | ||
1095 | } | 1093 | } |
1096 | 1094 | ||
1097 | 1095 | ||
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 55ee2d36d585..026a587eb8dd 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c | |||
@@ -34,9 +34,8 @@ | |||
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/module.h> | 36 | #include <linux/module.h> |
37 | #include <linux/usb.h> | ||
38 | #include <linux/usb_ch9.h> | 37 | #include <linux/usb_ch9.h> |
39 | #include <linux/usb_input.h> | 38 | #include <linux/usb/input.h> |
40 | #include "usb.h" | 39 | #include "usb.h" |
41 | #include "onetouch.h" | 40 | #include "onetouch.h" |
42 | #include "debug.h" | 41 | #include "debug.h" |
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 5f11e19eaae3..5715291ba540 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c | |||
@@ -286,11 +286,7 @@ static int bus_reset(struct scsi_cmnd *srb) | |||
286 | int result; | 286 | int result; |
287 | 287 | ||
288 | US_DEBUGP("%s called\n", __FUNCTION__); | 288 | US_DEBUGP("%s called\n", __FUNCTION__); |
289 | |||
290 | mutex_lock(&(us->dev_mutex)); | ||
291 | result = usb_stor_port_reset(us); | 289 | result = usb_stor_port_reset(us); |
292 | mutex_unlock(&us->dev_mutex); | ||
293 | |||
294 | return result < 0 ? FAILED : SUCCESS; | 290 | return result < 0 ? FAILED : SUCCESS; |
295 | } | 291 | } |
296 | 292 | ||
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index f2bc5c9e23d5..8fcec01dc622 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c | |||
@@ -131,28 +131,30 @@ static int usbat_write(struct us_data *us, | |||
131 | * Convenience function to perform a bulk read | 131 | * Convenience function to perform a bulk read |
132 | */ | 132 | */ |
133 | static int usbat_bulk_read(struct us_data *us, | 133 | static int usbat_bulk_read(struct us_data *us, |
134 | unsigned char *data, | 134 | unsigned char *data, |
135 | unsigned int len) | 135 | unsigned int len, |
136 | int use_sg) | ||
136 | { | 137 | { |
137 | if (len == 0) | 138 | if (len == 0) |
138 | return USB_STOR_XFER_GOOD; | 139 | return USB_STOR_XFER_GOOD; |
139 | 140 | ||
140 | US_DEBUGP("usbat_bulk_read: len = %d\n", len); | 141 | US_DEBUGP("usbat_bulk_read: len = %d\n", len); |
141 | return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, data, len, NULL); | 142 | return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, data, len, use_sg, NULL); |
142 | } | 143 | } |
143 | 144 | ||
144 | /* | 145 | /* |
145 | * Convenience function to perform a bulk write | 146 | * Convenience function to perform a bulk write |
146 | */ | 147 | */ |
147 | static int usbat_bulk_write(struct us_data *us, | 148 | static int usbat_bulk_write(struct us_data *us, |
148 | unsigned char *data, | 149 | unsigned char *data, |
149 | unsigned int len) | 150 | unsigned int len, |
151 | int use_sg) | ||
150 | { | 152 | { |
151 | if (len == 0) | 153 | if (len == 0) |
152 | return USB_STOR_XFER_GOOD; | 154 | return USB_STOR_XFER_GOOD; |
153 | 155 | ||
154 | US_DEBUGP("usbat_bulk_write: len = %d\n", len); | 156 | US_DEBUGP("usbat_bulk_write: len = %d\n", len); |
155 | return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, data, len, NULL); | 157 | return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, data, len, use_sg, NULL); |
156 | } | 158 | } |
157 | 159 | ||
158 | /* | 160 | /* |
@@ -317,7 +319,8 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes) | |||
317 | */ | 319 | */ |
318 | static int usbat_read_block(struct us_data *us, | 320 | static int usbat_read_block(struct us_data *us, |
319 | unsigned char *content, | 321 | unsigned char *content, |
320 | unsigned short len) | 322 | unsigned short len, |
323 | int use_sg) | ||
321 | { | 324 | { |
322 | int result; | 325 | int result; |
323 | unsigned char *command = us->iobuf; | 326 | unsigned char *command = us->iobuf; |
@@ -338,7 +341,7 @@ static int usbat_read_block(struct us_data *us, | |||
338 | if (result != USB_STOR_XFER_GOOD) | 341 | if (result != USB_STOR_XFER_GOOD) |
339 | return USB_STOR_TRANSPORT_ERROR; | 342 | return USB_STOR_TRANSPORT_ERROR; |
340 | 343 | ||
341 | result = usbat_bulk_read(us, content, len); | 344 | result = usbat_bulk_read(us, content, len, use_sg); |
342 | return (result == USB_STOR_XFER_GOOD ? | 345 | return (result == USB_STOR_XFER_GOOD ? |
343 | USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); | 346 | USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); |
344 | } | 347 | } |
@@ -350,7 +353,8 @@ static int usbat_write_block(struct us_data *us, | |||
350 | unsigned char access, | 353 | unsigned char access, |
351 | unsigned char *content, | 354 | unsigned char *content, |
352 | unsigned short len, | 355 | unsigned short len, |
353 | int minutes) | 356 | int minutes, |
357 | int use_sg) | ||
354 | { | 358 | { |
355 | int result; | 359 | int result; |
356 | unsigned char *command = us->iobuf; | 360 | unsigned char *command = us->iobuf; |
@@ -372,7 +376,7 @@ static int usbat_write_block(struct us_data *us, | |||
372 | if (result != USB_STOR_XFER_GOOD) | 376 | if (result != USB_STOR_XFER_GOOD) |
373 | return USB_STOR_TRANSPORT_ERROR; | 377 | return USB_STOR_TRANSPORT_ERROR; |
374 | 378 | ||
375 | result = usbat_bulk_write(us, content, len); | 379 | result = usbat_bulk_write(us, content, len, use_sg); |
376 | if (result != USB_STOR_XFER_GOOD) | 380 | if (result != USB_STOR_XFER_GOOD) |
377 | return USB_STOR_TRANSPORT_ERROR; | 381 | return USB_STOR_TRANSPORT_ERROR; |
378 | 382 | ||
@@ -465,7 +469,7 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us, | |||
465 | data[1+(j<<1)] = data_out[j]; | 469 | data[1+(j<<1)] = data_out[j]; |
466 | } | 470 | } |
467 | 471 | ||
468 | result = usbat_bulk_write(us, data, num_registers*2); | 472 | result = usbat_bulk_write(us, data, num_registers*2, 0); |
469 | if (result != USB_STOR_XFER_GOOD) | 473 | if (result != USB_STOR_XFER_GOOD) |
470 | return USB_STOR_TRANSPORT_ERROR; | 474 | return USB_STOR_TRANSPORT_ERROR; |
471 | 475 | ||
@@ -583,7 +587,7 @@ static int usbat_multiple_write(struct us_data *us, | |||
583 | } | 587 | } |
584 | 588 | ||
585 | /* Send the data */ | 589 | /* Send the data */ |
586 | result = usbat_bulk_write(us, data, num_registers*2); | 590 | result = usbat_bulk_write(us, data, num_registers*2, 0); |
587 | if (result != USB_STOR_XFER_GOOD) | 591 | if (result != USB_STOR_XFER_GOOD) |
588 | return USB_STOR_TRANSPORT_ERROR; | 592 | return USB_STOR_TRANSPORT_ERROR; |
589 | 593 | ||
@@ -606,8 +610,9 @@ static int usbat_multiple_write(struct us_data *us, | |||
606 | * other related details) are defined beforehand with _set_shuttle_features(). | 610 | * other related details) are defined beforehand with _set_shuttle_features(). |
607 | */ | 611 | */ |
608 | static int usbat_read_blocks(struct us_data *us, | 612 | static int usbat_read_blocks(struct us_data *us, |
609 | unsigned char *buffer, | 613 | unsigned char *buffer, |
610 | int len) | 614 | int len, |
615 | int use_sg) | ||
611 | { | 616 | { |
612 | int result; | 617 | int result; |
613 | unsigned char *command = us->iobuf; | 618 | unsigned char *command = us->iobuf; |
@@ -627,7 +632,7 @@ static int usbat_read_blocks(struct us_data *us, | |||
627 | return USB_STOR_TRANSPORT_FAILED; | 632 | return USB_STOR_TRANSPORT_FAILED; |
628 | 633 | ||
629 | /* Read the blocks we just asked for */ | 634 | /* Read the blocks we just asked for */ |
630 | result = usbat_bulk_read(us, buffer, len); | 635 | result = usbat_bulk_read(us, buffer, len, use_sg); |
631 | if (result != USB_STOR_XFER_GOOD) | 636 | if (result != USB_STOR_XFER_GOOD) |
632 | return USB_STOR_TRANSPORT_FAILED; | 637 | return USB_STOR_TRANSPORT_FAILED; |
633 | 638 | ||
@@ -648,7 +653,8 @@ static int usbat_read_blocks(struct us_data *us, | |||
648 | */ | 653 | */ |
649 | static int usbat_write_blocks(struct us_data *us, | 654 | static int usbat_write_blocks(struct us_data *us, |
650 | unsigned char *buffer, | 655 | unsigned char *buffer, |
651 | int len) | 656 | int len, |
657 | int use_sg) | ||
652 | { | 658 | { |
653 | int result; | 659 | int result; |
654 | unsigned char *command = us->iobuf; | 660 | unsigned char *command = us->iobuf; |
@@ -668,7 +674,7 @@ static int usbat_write_blocks(struct us_data *us, | |||
668 | return USB_STOR_TRANSPORT_FAILED; | 674 | return USB_STOR_TRANSPORT_FAILED; |
669 | 675 | ||
670 | /* Write the data */ | 676 | /* Write the data */ |
671 | result = usbat_bulk_write(us, buffer, len); | 677 | result = usbat_bulk_write(us, buffer, len, use_sg); |
672 | if (result != USB_STOR_XFER_GOOD) | 678 | if (result != USB_STOR_XFER_GOOD) |
673 | return USB_STOR_TRANSPORT_FAILED; | 679 | return USB_STOR_TRANSPORT_FAILED; |
674 | 680 | ||
@@ -887,22 +893,28 @@ static int usbat_identify_device(struct us_data *us, | |||
887 | * Set the transport function based on the device type | 893 | * Set the transport function based on the device type |
888 | */ | 894 | */ |
889 | static int usbat_set_transport(struct us_data *us, | 895 | static int usbat_set_transport(struct us_data *us, |
890 | struct usbat_info *info) | 896 | struct usbat_info *info, |
897 | int devicetype) | ||
891 | { | 898 | { |
892 | int rc; | ||
893 | 899 | ||
894 | if (!info->devicetype) { | 900 | if (!info->devicetype) |
895 | rc = usbat_identify_device(us, info); | 901 | info->devicetype = devicetype; |
896 | if (rc != USB_STOR_TRANSPORT_GOOD) { | ||
897 | US_DEBUGP("usbat_set_transport: Could not identify device\n"); | ||
898 | return 1; | ||
899 | } | ||
900 | } | ||
901 | 902 | ||
902 | if (usbat_get_device_type(us) == USBAT_DEV_HP8200) | 903 | if (!info->devicetype) |
904 | usbat_identify_device(us, info); | ||
905 | |||
906 | switch (info->devicetype) { | ||
907 | default: | ||
908 | return USB_STOR_TRANSPORT_ERROR; | ||
909 | |||
910 | case USBAT_DEV_HP8200: | ||
903 | us->transport = usbat_hp8200e_transport; | 911 | us->transport = usbat_hp8200e_transport; |
904 | else if (usbat_get_device_type(us) == USBAT_DEV_FLASH) | 912 | break; |
913 | |||
914 | case USBAT_DEV_FLASH: | ||
905 | us->transport = usbat_flash_transport; | 915 | us->transport = usbat_flash_transport; |
916 | break; | ||
917 | } | ||
906 | 918 | ||
907 | return 0; | 919 | return 0; |
908 | } | 920 | } |
@@ -947,7 +959,7 @@ static int usbat_flash_get_sector_count(struct us_data *us, | |||
947 | msleep(100); | 959 | msleep(100); |
948 | 960 | ||
949 | /* Read the device identification data */ | 961 | /* Read the device identification data */ |
950 | rc = usbat_read_block(us, reply, 512); | 962 | rc = usbat_read_block(us, reply, 512, 0); |
951 | if (rc != USB_STOR_TRANSPORT_GOOD) | 963 | if (rc != USB_STOR_TRANSPORT_GOOD) |
952 | goto leave; | 964 | goto leave; |
953 | 965 | ||
@@ -1031,7 +1043,7 @@ static int usbat_flash_read_data(struct us_data *us, | |||
1031 | goto leave; | 1043 | goto leave; |
1032 | 1044 | ||
1033 | /* Read the data we just requested */ | 1045 | /* Read the data we just requested */ |
1034 | result = usbat_read_blocks(us, buffer, len); | 1046 | result = usbat_read_blocks(us, buffer, len, 0); |
1035 | if (result != USB_STOR_TRANSPORT_GOOD) | 1047 | if (result != USB_STOR_TRANSPORT_GOOD) |
1036 | goto leave; | 1048 | goto leave; |
1037 | 1049 | ||
@@ -1125,7 +1137,7 @@ static int usbat_flash_write_data(struct us_data *us, | |||
1125 | goto leave; | 1137 | goto leave; |
1126 | 1138 | ||
1127 | /* Write the data */ | 1139 | /* Write the data */ |
1128 | result = usbat_write_blocks(us, buffer, len); | 1140 | result = usbat_write_blocks(us, buffer, len, 0); |
1129 | if (result != USB_STOR_TRANSPORT_GOOD) | 1141 | if (result != USB_STOR_TRANSPORT_GOOD) |
1130 | goto leave; | 1142 | goto leave; |
1131 | 1143 | ||
@@ -1310,7 +1322,7 @@ static int usbat_select_and_test_registers(struct us_data *us) | |||
1310 | /* | 1322 | /* |
1311 | * Initialize the USBAT processor and the storage device | 1323 | * Initialize the USBAT processor and the storage device |
1312 | */ | 1324 | */ |
1313 | int init_usbat(struct us_data *us) | 1325 | static int init_usbat(struct us_data *us, int devicetype) |
1314 | { | 1326 | { |
1315 | int rc; | 1327 | int rc; |
1316 | struct usbat_info *info; | 1328 | struct usbat_info *info; |
@@ -1392,7 +1404,7 @@ int init_usbat(struct us_data *us) | |||
1392 | US_DEBUGP("INIT 9\n"); | 1404 | US_DEBUGP("INIT 9\n"); |
1393 | 1405 | ||
1394 | /* At this point, we need to detect which device we are using */ | 1406 | /* At this point, we need to detect which device we are using */ |
1395 | if (usbat_set_transport(us, info)) | 1407 | if (usbat_set_transport(us, info, devicetype)) |
1396 | return USB_STOR_TRANSPORT_ERROR; | 1408 | return USB_STOR_TRANSPORT_ERROR; |
1397 | 1409 | ||
1398 | US_DEBUGP("INIT 10\n"); | 1410 | US_DEBUGP("INIT 10\n"); |
@@ -1503,10 +1515,10 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1503 | * AT SPEED 4 IS UNRELIABLE!!! | 1515 | * AT SPEED 4 IS UNRELIABLE!!! |
1504 | */ | 1516 | */ |
1505 | 1517 | ||
1506 | if ( (result = usbat_write_block(us, | 1518 | if ((result = usbat_write_block(us, |
1507 | USBAT_ATA, srb->cmnd, 12, | 1519 | USBAT_ATA, srb->cmnd, 12, |
1508 | srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) != | 1520 | (srb->cmnd[0]==GPCMD_BLANK ? 75 : 10), 0) != |
1509 | USB_STOR_TRANSPORT_GOOD) { | 1521 | USB_STOR_TRANSPORT_GOOD)) { |
1510 | return result; | 1522 | return result; |
1511 | } | 1523 | } |
1512 | 1524 | ||
@@ -1533,7 +1545,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1533 | len = *status; | 1545 | len = *status; |
1534 | 1546 | ||
1535 | 1547 | ||
1536 | result = usbat_read_block(us, srb->request_buffer, len); | 1548 | result = usbat_read_block(us, srb->request_buffer, len, srb->use_sg); |
1537 | 1549 | ||
1538 | /* Debug-print the first 32 bytes of the transfer */ | 1550 | /* Debug-print the first 32 bytes of the transfer */ |
1539 | 1551 | ||
@@ -1695,6 +1707,22 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) | |||
1695 | return USB_STOR_TRANSPORT_FAILED; | 1707 | return USB_STOR_TRANSPORT_FAILED; |
1696 | } | 1708 | } |
1697 | 1709 | ||
1710 | int init_usbat_cd(struct us_data *us) | ||
1711 | { | ||
1712 | return init_usbat(us, USBAT_DEV_HP8200); | ||
1713 | } | ||
1714 | |||
1715 | |||
1716 | int init_usbat_flash(struct us_data *us) | ||
1717 | { | ||
1718 | return init_usbat(us, USBAT_DEV_FLASH); | ||
1719 | } | ||
1720 | |||
1721 | int init_usbat_probe(struct us_data *us) | ||
1722 | { | ||
1723 | return init_usbat(us, 0); | ||
1724 | } | ||
1725 | |||
1698 | /* | 1726 | /* |
1699 | * Default transport function. Attempts to detect which transport function | 1727 | * Default transport function. Attempts to detect which transport function |
1700 | * should be called, makes it the new default, and calls it. | 1728 | * should be called, makes it the new default, and calls it. |
@@ -1708,9 +1736,8 @@ int usbat_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1708 | { | 1736 | { |
1709 | struct usbat_info *info = (struct usbat_info*) (us->extra); | 1737 | struct usbat_info *info = (struct usbat_info*) (us->extra); |
1710 | 1738 | ||
1711 | if (usbat_set_transport(us, info)) | 1739 | if (usbat_set_transport(us, info, 0)) |
1712 | return USB_STOR_TRANSPORT_ERROR; | 1740 | return USB_STOR_TRANSPORT_ERROR; |
1713 | 1741 | ||
1714 | return us->transport(srb, us); | 1742 | return us->transport(srb, us); |
1715 | } | 1743 | } |
1716 | |||
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h index 25e7d8b340b8..3ddf143a1dec 100644 --- a/drivers/usb/storage/shuttle_usbat.h +++ b/drivers/usb/storage/shuttle_usbat.h | |||
@@ -106,7 +106,9 @@ | |||
106 | #define USBAT_FEAT_ET2 0x01 | 106 | #define USBAT_FEAT_ET2 0x01 |
107 | 107 | ||
108 | extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us); | 108 | extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us); |
109 | extern int init_usbat(struct us_data *us); | 109 | extern int init_usbat_cd(struct us_data *us); |
110 | extern int init_usbat_flash(struct us_data *us); | ||
111 | extern int init_usbat_probe(struct us_data *us); | ||
110 | 112 | ||
111 | struct usbat_info { | 113 | struct usbat_info { |
112 | int devicetype; | 114 | int devicetype; |
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 7ca896a342e3..19b25c5cafd4 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c | |||
@@ -115,19 +115,6 @@ static void usb_stor_blocking_completion(struct urb *urb, struct pt_regs *regs) | |||
115 | 115 | ||
116 | complete(urb_done_ptr); | 116 | complete(urb_done_ptr); |
117 | } | 117 | } |
118 | |||
119 | /* This is the timeout handler which will cancel an URB when its timeout | ||
120 | * expires. | ||
121 | */ | ||
122 | static void timeout_handler(unsigned long us_) | ||
123 | { | ||
124 | struct us_data *us = (struct us_data *) us_; | ||
125 | |||
126 | if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) { | ||
127 | US_DEBUGP("Timeout -- cancelling URB\n"); | ||
128 | usb_unlink_urb(us->current_urb); | ||
129 | } | ||
130 | } | ||
131 | 118 | ||
132 | /* This is the common part of the URB message submission code | 119 | /* This is the common part of the URB message submission code |
133 | * | 120 | * |
@@ -138,7 +125,7 @@ static void timeout_handler(unsigned long us_) | |||
138 | static int usb_stor_msg_common(struct us_data *us, int timeout) | 125 | static int usb_stor_msg_common(struct us_data *us, int timeout) |
139 | { | 126 | { |
140 | struct completion urb_done; | 127 | struct completion urb_done; |
141 | struct timer_list to_timer; | 128 | long timeleft; |
142 | int status; | 129 | int status; |
143 | 130 | ||
144 | /* don't submit URBs during abort/disconnect processing */ | 131 | /* don't submit URBs during abort/disconnect processing */ |
@@ -185,22 +172,17 @@ static int usb_stor_msg_common(struct us_data *us, int timeout) | |||
185 | } | 172 | } |
186 | } | 173 | } |
187 | 174 | ||
188 | /* submit the timeout timer, if a timeout was requested */ | ||
189 | if (timeout > 0) { | ||
190 | init_timer(&to_timer); | ||
191 | to_timer.expires = jiffies + timeout; | ||
192 | to_timer.function = timeout_handler; | ||
193 | to_timer.data = (unsigned long) us; | ||
194 | add_timer(&to_timer); | ||
195 | } | ||
196 | |||
197 | /* wait for the completion of the URB */ | 175 | /* wait for the completion of the URB */ |
198 | wait_for_completion(&urb_done); | 176 | timeleft = wait_for_completion_interruptible_timeout( |
199 | clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); | 177 | &urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT); |
200 | 178 | ||
201 | /* clean up the timeout timer */ | 179 | clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); |
202 | if (timeout > 0) | 180 | |
203 | del_timer_sync(&to_timer); | 181 | if (timeleft <= 0) { |
182 | US_DEBUGP("%s -- cancelling URB\n", | ||
183 | timeleft == 0 ? "Timeout" : "Signal"); | ||
184 | usb_unlink_urb(us->current_urb); | ||
185 | } | ||
204 | 186 | ||
205 | /* return the URB status */ | 187 | /* return the URB status */ |
206 | return us->current_urb->status; | 188 | return us->current_urb->status; |
@@ -721,16 +703,19 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
721 | * device reset. */ | 703 | * device reset. */ |
722 | Handle_Errors: | 704 | Handle_Errors: |
723 | 705 | ||
724 | /* Let the SCSI layer know we are doing a reset, set the | 706 | /* Set the RESETTING bit, and clear the ABORTING bit so that |
725 | * RESETTING bit, and clear the ABORTING bit so that the reset | 707 | * the reset may proceed. */ |
726 | * may proceed. */ | ||
727 | scsi_lock(us_to_host(us)); | 708 | scsi_lock(us_to_host(us)); |
728 | usb_stor_report_bus_reset(us); | ||
729 | set_bit(US_FLIDX_RESETTING, &us->flags); | 709 | set_bit(US_FLIDX_RESETTING, &us->flags); |
730 | clear_bit(US_FLIDX_ABORTING, &us->flags); | 710 | clear_bit(US_FLIDX_ABORTING, &us->flags); |
731 | scsi_unlock(us_to_host(us)); | 711 | scsi_unlock(us_to_host(us)); |
732 | 712 | ||
713 | /* We must release the device lock because the pre_reset routine | ||
714 | * will want to acquire it. */ | ||
715 | mutex_unlock(&us->dev_mutex); | ||
733 | result = usb_stor_port_reset(us); | 716 | result = usb_stor_port_reset(us); |
717 | mutex_lock(&us->dev_mutex); | ||
718 | |||
734 | if (result < 0) { | 719 | if (result < 0) { |
735 | scsi_lock(us_to_host(us)); | 720 | scsi_lock(us_to_host(us)); |
736 | usb_stor_report_device_reset(us); | 721 | usb_stor_report_device_reset(us); |
@@ -1214,31 +1199,30 @@ int usb_stor_Bulk_reset(struct us_data *us) | |||
1214 | 0, us->ifnum, NULL, 0); | 1199 | 0, us->ifnum, NULL, 0); |
1215 | } | 1200 | } |
1216 | 1201 | ||
1217 | /* Issue a USB port reset to the device. But don't do anything if | 1202 | /* Issue a USB port reset to the device. The caller must not hold |
1218 | * there's more than one interface in the device, so that other users | 1203 | * us->dev_mutex. |
1219 | * are not affected. */ | 1204 | */ |
1220 | int usb_stor_port_reset(struct us_data *us) | 1205 | int usb_stor_port_reset(struct us_data *us) |
1221 | { | 1206 | { |
1222 | int result, rc; | 1207 | int result, rc_lock; |
1223 | 1208 | ||
1224 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { | 1209 | result = rc_lock = |
1225 | result = -EIO; | 1210 | usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); |
1226 | US_DEBUGP("No reset during disconnect\n"); | 1211 | if (result < 0) |
1227 | } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) { | 1212 | US_DEBUGP("unable to lock device for reset: %d\n", result); |
1228 | result = -EBUSY; | 1213 | else { |
1229 | US_DEBUGP("Refusing to reset a multi-interface device\n"); | 1214 | /* Were we disconnected while waiting for the lock? */ |
1230 | } else { | 1215 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { |
1231 | result = rc = | 1216 | result = -EIO; |
1232 | usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); | 1217 | US_DEBUGP("No reset during disconnect\n"); |
1233 | if (result < 0) { | ||
1234 | US_DEBUGP("unable to lock device for reset: %d\n", | ||
1235 | result); | ||
1236 | } else { | 1218 | } else { |
1237 | result = usb_reset_device(us->pusb_dev); | 1219 | result = usb_reset_composite_device( |
1238 | if (rc) | 1220 | us->pusb_dev, us->pusb_intf); |
1239 | usb_unlock_device(us->pusb_dev); | 1221 | US_DEBUGP("usb_reset_composite_device returns %d\n", |
1240 | US_DEBUGP("usb_reset_device returns %d\n", result); | 1222 | result); |
1241 | } | 1223 | } |
1224 | if (rc_lock) | ||
1225 | usb_unlock_device(us->pusb_dev); | ||
1242 | } | 1226 | } |
1243 | return result; | 1227 | return result; |
1244 | } | 1228 | } |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index aec5ea8682d5..543244d421c1 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -78,12 +78,12 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, | |||
78 | UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, | 78 | UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, |
79 | "HP", | 79 | "HP", |
80 | "CD-Writer+ 8200e", | 80 | "CD-Writer+ 8200e", |
81 | US_SC_8070, US_PR_USBAT, init_usbat, 0), | 81 | US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), |
82 | 82 | ||
83 | UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, | 83 | UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, |
84 | "HP", | 84 | "HP", |
85 | "CD-Writer+ CD-4e", | 85 | "CD-Writer+ CD-4e", |
86 | US_SC_8070, US_PR_USBAT, init_usbat, 0), | 86 | US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), |
87 | #endif | 87 | #endif |
88 | 88 | ||
89 | /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net> | 89 | /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net> |
@@ -133,6 +133,14 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, | |||
133 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 133 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
134 | US_FL_IGNORE_RESIDUE ), | 134 | US_FL_IGNORE_RESIDUE ), |
135 | 135 | ||
136 | /* Reported by Jiri Slaby <jirislaby@gmail.com> and | ||
137 | * Rene C. Castberg <Rene@Castberg.org> */ | ||
138 | UNUSUAL_DEV( 0x0421, 0x0446, 0x0100, 0x0100, | ||
139 | "Nokia", | ||
140 | "N80", | ||
141 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
142 | US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), | ||
143 | |||
136 | /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */ | 144 | /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */ |
137 | UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, | 145 | UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, |
138 | "SMSC", | 146 | "SMSC", |
@@ -216,6 +224,14 @@ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, | |||
216 | "DVD-CAM DZ-MV100A Camcorder", | 224 | "DVD-CAM DZ-MV100A Camcorder", |
217 | US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN), | 225 | US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN), |
218 | 226 | ||
227 | /* Patch for Nikon coolpix 2000 | ||
228 | * Submitted by Fabien Cosse <fabien.cosse@wanadoo.fr>*/ | ||
229 | UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, | ||
230 | "NIKON", | ||
231 | "NIKON DSC E2000", | ||
232 | US_SC_DEVICE, US_PR_DEVICE,NULL, | ||
233 | US_FL_NOT_LOCKABLE ), | ||
234 | |||
219 | /* Reported by Andreas Bockhold <andreas@bockionline.de> */ | 235 | /* Reported by Andreas Bockhold <andreas@bockionline.de> */ |
220 | UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, | 236 | UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, |
221 | "NIKON", | 237 | "NIKON", |
@@ -223,13 +239,12 @@ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, | |||
223 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 239 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
224 | US_FL_FIX_CAPACITY), | 240 | US_FL_FIX_CAPACITY), |
225 | 241 | ||
226 | /* Patch for Nikon coolpix 2000 | 242 | /* Reported by Jamie Kitson <jamie@staberinde.fsnet.co.uk> */ |
227 | * Submitted by Fabien Cosse <fabien.cosse@wanadoo.fr>*/ | 243 | UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, |
228 | UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, | ||
229 | "NIKON", | 244 | "NIKON", |
230 | "NIKON DSC E2000", | 245 | "NIKON DSC D70s", |
231 | US_SC_DEVICE, US_PR_DEVICE,NULL, | 246 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
232 | US_FL_NOT_LOCKABLE ), | 247 | US_FL_FIX_CAPACITY), |
233 | 248 | ||
234 | /* BENQ DC5330 | 249 | /* BENQ DC5330 |
235 | * Reported by Manuel Fombuena <mfombuena@ya.com> and | 250 | * Reported by Manuel Fombuena <mfombuena@ya.com> and |
@@ -393,7 +408,7 @@ UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100, | |||
393 | UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, | 408 | UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, |
394 | "Shuttle/SCM", | 409 | "Shuttle/SCM", |
395 | "USBAT-02", | 410 | "USBAT-02", |
396 | US_SC_SCSI, US_PR_USBAT, init_usbat, | 411 | US_SC_SCSI, US_PR_USBAT, init_usbat_flash, |
397 | US_FL_SINGLE_LUN), | 412 | US_FL_SINGLE_LUN), |
398 | #endif | 413 | #endif |
399 | 414 | ||
@@ -797,7 +812,7 @@ UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, | |||
797 | UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, | 812 | UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, |
798 | "Sandisk", | 813 | "Sandisk", |
799 | "ImageMate SDDR-05b", | 814 | "ImageMate SDDR-05b", |
800 | US_SC_SCSI, US_PR_USBAT, init_usbat, | 815 | US_SC_SCSI, US_PR_USBAT, init_usbat_flash, |
801 | US_FL_SINGLE_LUN ), | 816 | US_FL_SINGLE_LUN ), |
802 | #endif | 817 | #endif |
803 | 818 | ||
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index dd108634348e..e232c7c89909 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -221,6 +221,37 @@ static int storage_resume(struct usb_interface *iface) | |||
221 | #endif /* CONFIG_PM */ | 221 | #endif /* CONFIG_PM */ |
222 | 222 | ||
223 | /* | 223 | /* |
224 | * The next two routines get called just before and just after | ||
225 | * a USB port reset, whether from this driver or a different one. | ||
226 | */ | ||
227 | |||
228 | static void storage_pre_reset(struct usb_interface *iface) | ||
229 | { | ||
230 | struct us_data *us = usb_get_intfdata(iface); | ||
231 | |||
232 | US_DEBUGP("%s\n", __FUNCTION__); | ||
233 | |||
234 | /* Make sure no command runs during the reset */ | ||
235 | mutex_lock(&us->dev_mutex); | ||
236 | } | ||
237 | |||
238 | static void storage_post_reset(struct usb_interface *iface) | ||
239 | { | ||
240 | struct us_data *us = usb_get_intfdata(iface); | ||
241 | |||
242 | US_DEBUGP("%s\n", __FUNCTION__); | ||
243 | |||
244 | /* Report the reset to the SCSI core */ | ||
245 | scsi_lock(us_to_host(us)); | ||
246 | usb_stor_report_bus_reset(us); | ||
247 | scsi_unlock(us_to_host(us)); | ||
248 | |||
249 | /* FIXME: Notify the subdrivers that they need to reinitialize | ||
250 | * the device */ | ||
251 | mutex_unlock(&us->dev_mutex); | ||
252 | } | ||
253 | |||
254 | /* | ||
224 | * fill_inquiry_response takes an unsigned char array (which must | 255 | * fill_inquiry_response takes an unsigned char array (which must |
225 | * be at least 36 characters) and populates the vendor name, | 256 | * be at least 36 characters) and populates the vendor name, |
226 | * product name, and revision fields. Then the array is copied | 257 | * product name, and revision fields. Then the array is copied |
@@ -593,6 +624,15 @@ static int get_transport(struct us_data *us) | |||
593 | break; | 624 | break; |
594 | #endif | 625 | #endif |
595 | 626 | ||
627 | #ifdef CONFIG_USB_STORAGE_ALAUDA | ||
628 | case US_PR_ALAUDA: | ||
629 | us->transport_name = "Alauda Control/Bulk"; | ||
630 | us->transport = alauda_transport; | ||
631 | us->transport_reset = usb_stor_Bulk_reset; | ||
632 | us->max_lun = 1; | ||
633 | break; | ||
634 | #endif | ||
635 | |||
596 | default: | 636 | default: |
597 | return -EIO; | 637 | return -EIO; |
598 | } | 638 | } |
@@ -648,15 +688,6 @@ static int get_protocol(struct us_data *us) | |||
648 | break; | 688 | break; |
649 | #endif | 689 | #endif |
650 | 690 | ||
651 | #ifdef CONFIG_USB_STORAGE_ALAUDA | ||
652 | case US_PR_ALAUDA: | ||
653 | us->transport_name = "Alauda Control/Bulk"; | ||
654 | us->transport = alauda_transport; | ||
655 | us->transport_reset = usb_stor_Bulk_reset; | ||
656 | us->max_lun = 1; | ||
657 | break; | ||
658 | #endif | ||
659 | |||
660 | default: | 691 | default: |
661 | return -EIO; | 692 | return -EIO; |
662 | } | 693 | } |
@@ -1002,6 +1033,8 @@ static struct usb_driver usb_storage_driver = { | |||
1002 | .suspend = storage_suspend, | 1033 | .suspend = storage_suspend, |
1003 | .resume = storage_resume, | 1034 | .resume = storage_resume, |
1004 | #endif | 1035 | #endif |
1036 | .pre_reset = storage_pre_reset, | ||
1037 | .post_reset = storage_post_reset, | ||
1005 | .id_table = storage_usb_ids, | 1038 | .id_table = storage_usb_ids, |
1006 | }; | 1039 | }; |
1007 | 1040 | ||