diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-24 08:41:41 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-24 13:07:53 -0400 |
| commit | 816724e65c72a90a44fbad0ef0b59b186c85fa90 (patch) | |
| tree | 421fa29aedff988e392f92780637553e275d37a0 /drivers/usb | |
| parent | 70ac4385a13f78bc478f26d317511893741b05bd (diff) | |
| parent | d384ea691fe4ea8c2dd5b9b8d9042eb181776f18 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Conflicts:
fs/nfs/inode.c
fs/super.c
Fix conflicts between patch 'NFS: Split fs/nfs/inode.c' and patch
'VFS: Permit filesystem to override root dentry on mount'
Diffstat (limited to 'drivers/usb')
113 files changed, 3799 insertions, 2062 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..3f8e06279c92 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 | } |
| @@ -1078,7 +1078,9 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg) | |||
| 1078 | if (copy_from_user(&uurb, arg, sizeof(uurb))) | 1078 | if (copy_from_user(&uurb, arg, sizeof(uurb))) |
| 1079 | return -EFAULT; | 1079 | return -EFAULT; |
| 1080 | 1080 | ||
| 1081 | return proc_do_submiturb(ps, &uurb, (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), arg); | 1081 | return proc_do_submiturb(ps, &uurb, |
| 1082 | (struct usbdevfs_iso_packet_desc __user *)uurb.iso_frame_desc, | ||
| 1083 | arg); | ||
| 1082 | } | 1084 | } |
| 1083 | 1085 | ||
| 1084 | static int proc_unlinkurb(struct dev_state *ps, void __user *arg) | 1086 | static int proc_unlinkurb(struct dev_state *ps, void __user *arg) |
| @@ -1203,7 +1205,9 @@ static int proc_submiturb_compat(struct dev_state *ps, void __user *arg) | |||
| 1203 | if (get_urb32(&uurb,(struct usbdevfs_urb32 *)arg)) | 1205 | if (get_urb32(&uurb,(struct usbdevfs_urb32 *)arg)) |
| 1204 | return -EFAULT; | 1206 | return -EFAULT; |
| 1205 | 1207 | ||
| 1206 | return proc_do_submiturb(ps, &uurb, ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, arg); | 1208 | return proc_do_submiturb(ps, &uurb, |
| 1209 | (struct usbdevfs_iso_packet_desc __user *)uurb.iso_frame_desc, | ||
| 1210 | arg); | ||
| 1207 | } | 1211 | } |
| 1208 | 1212 | ||
| 1209 | static int processcompl_compat(struct async *as, void __user * __user *arg) | 1213 | static int processcompl_compat(struct async *as, void __user * __user *arg) |
| @@ -1576,16 +1580,16 @@ static void usbdev_add(struct usb_device *dev) | |||
| 1576 | { | 1580 | { |
| 1577 | int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); | 1581 | int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); |
| 1578 | 1582 | ||
| 1579 | dev->class_dev = class_device_create(usb_device_class, NULL, | 1583 | dev->usbfs_dev = device_create(usb_device_class, &dev->dev, |
| 1580 | MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev, | 1584 | MKDEV(USB_DEVICE_MAJOR, minor), |
| 1581 | "usbdev%d.%d", dev->bus->busnum, dev->devnum); | 1585 | "usbdev%d.%d", dev->bus->busnum, dev->devnum); |
| 1582 | 1586 | ||
| 1583 | dev->class_dev->class_data = dev; | 1587 | dev->usbfs_dev->platform_data = dev; |
| 1584 | } | 1588 | } |
| 1585 | 1589 | ||
| 1586 | static void usbdev_remove(struct usb_device *dev) | 1590 | static void usbdev_remove(struct usb_device *dev) |
| 1587 | { | 1591 | { |
| 1588 | class_device_unregister(dev->class_dev); | 1592 | device_unregister(dev->usbfs_dev); |
| 1589 | } | 1593 | } |
| 1590 | 1594 | ||
| 1591 | static int usbdev_notify(struct notifier_block *self, unsigned long action, | 1595 | 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 695b90a17a68..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 = { |
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/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/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/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 | ||
