diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-07-13 13:23:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-07-13 13:23:03 -0400 |
commit | 51feb98d2547a389be2f666514f5bcd658f79eab (patch) | |
tree | bd3d3eb486a0008340afd5807d9d2db12ec3b7b3 /drivers/usb | |
parent | 8f8f013478133eb98e35e1d669c98c5e39d769c7 (diff) | |
parent | dc7520c17982ca4232233d2781e5cde29e58fbad (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (48 commits)
USB: otg: fix module reinsert issue
USB: handle zero-length usbfs submissions correctly
USB: EHCI: report actual_length for iso transfers
USB: option: remove unnecessary and erroneous code
USB: cypress_m8: remove invalid Clear-Halt
USB: musb_host: undo incorrect change in musb_advance_schedule()
USB: fix LANGID=0 regression
USB: serial: sierra driver id_table additions
USB serial: Add ID for Turtelizer, an FT2232L-based JTAG/RS-232 adapter.
USB: fix race leading to a write after kfree in usbfs
USB: Sierra: fix oops upon device close
USB: option.c: add A-Link 3GU device id
USB: Serial: Add support for Arkham Technology adapters
USB: Fix option_ms regression in 2.6.31-rc2
USB: gadget audio: select SND_PCM
USB: ftdi: support NDI devices
Revert USB: usbfs: deprecate and hide option for !embedded
USB: usb.h: fix kernel-doc notation
USB: RNDIS gadget, fix issues talking from PXA
USB: serial: FTDI with product code FB80 and vendor id 0403
...
Diffstat (limited to 'drivers/usb')
46 files changed, 574 insertions, 2204 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 3f1045993474..5b15d9d8896b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -387,6 +387,7 @@ static void acm_rx_tasklet(unsigned long _acm) | |||
387 | struct acm_ru *rcv; | 387 | struct acm_ru *rcv; |
388 | unsigned long flags; | 388 | unsigned long flags; |
389 | unsigned char throttled; | 389 | unsigned char throttled; |
390 | struct usb_host_endpoint *ep; | ||
390 | 391 | ||
391 | dbg("Entering acm_rx_tasklet"); | 392 | dbg("Entering acm_rx_tasklet"); |
392 | 393 | ||
@@ -462,11 +463,20 @@ urbs: | |||
462 | 463 | ||
463 | rcv->buffer = buf; | 464 | rcv->buffer = buf; |
464 | 465 | ||
465 | usb_fill_bulk_urb(rcv->urb, acm->dev, | 466 | ep = (usb_pipein(acm->rx_endpoint) ? acm->dev->ep_in : acm->dev->ep_out) |
466 | acm->rx_endpoint, | 467 | [usb_pipeendpoint(acm->rx_endpoint)]; |
467 | buf->base, | 468 | if (usb_endpoint_xfer_int(&ep->desc)) |
468 | acm->readsize, | 469 | usb_fill_int_urb(rcv->urb, acm->dev, |
469 | acm_read_bulk, rcv); | 470 | acm->rx_endpoint, |
471 | buf->base, | ||
472 | acm->readsize, | ||
473 | acm_read_bulk, rcv, ep->desc.bInterval); | ||
474 | else | ||
475 | usb_fill_bulk_urb(rcv->urb, acm->dev, | ||
476 | acm->rx_endpoint, | ||
477 | buf->base, | ||
478 | acm->readsize, | ||
479 | acm_read_bulk, rcv); | ||
470 | rcv->urb->transfer_dma = buf->dma; | 480 | rcv->urb->transfer_dma = buf->dma; |
471 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 481 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
472 | 482 | ||
@@ -1227,9 +1237,14 @@ made_compressed_probe: | |||
1227 | goto alloc_fail7; | 1237 | goto alloc_fail7; |
1228 | } | 1238 | } |
1229 | 1239 | ||
1230 | usb_fill_bulk_urb(snd->urb, usb_dev, | 1240 | if (usb_endpoint_xfer_int(epwrite)) |
1231 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), | 1241 | usb_fill_int_urb(snd->urb, usb_dev, |
1232 | NULL, acm->writesize, acm_write_bulk, snd); | 1242 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), |
1243 | NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); | ||
1244 | else | ||
1245 | usb_fill_bulk_urb(snd->urb, usb_dev, | ||
1246 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), | ||
1247 | NULL, acm->writesize, acm_write_bulk, snd); | ||
1233 | snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1248 | snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
1234 | snd->instance = acm; | 1249 | snd->instance = acm; |
1235 | } | 1250 | } |
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 3703789d0d2a..b09a527f7341 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
@@ -751,7 +751,7 @@ static int get_capabilities(struct usbtmc_device_data *data) | |||
751 | { | 751 | { |
752 | struct device *dev = &data->usb_dev->dev; | 752 | struct device *dev = &data->usb_dev->dev; |
753 | char *buffer; | 753 | char *buffer; |
754 | int rv; | 754 | int rv = 0; |
755 | 755 | ||
756 | buffer = kmalloc(0x18, GFP_KERNEL); | 756 | buffer = kmalloc(0x18, GFP_KERNEL); |
757 | if (!buffer) | 757 | if (!buffer) |
@@ -763,7 +763,7 @@ static int get_capabilities(struct usbtmc_device_data *data) | |||
763 | 0, 0, buffer, 0x18, USBTMC_TIMEOUT); | 763 | 0, 0, buffer, 0x18, USBTMC_TIMEOUT); |
764 | if (rv < 0) { | 764 | if (rv < 0) { |
765 | dev_err(dev, "usb_control_msg returned %d\n", rv); | 765 | dev_err(dev, "usb_control_msg returned %d\n", rv); |
766 | return rv; | 766 | goto err_out; |
767 | } | 767 | } |
768 | 768 | ||
769 | dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); | 769 | dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); |
@@ -773,7 +773,8 @@ static int get_capabilities(struct usbtmc_device_data *data) | |||
773 | dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]); | 773 | dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]); |
774 | if (buffer[0] != USBTMC_STATUS_SUCCESS) { | 774 | if (buffer[0] != USBTMC_STATUS_SUCCESS) { |
775 | dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); | 775 | dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); |
776 | return -EPERM; | 776 | rv = -EPERM; |
777 | goto err_out; | ||
777 | } | 778 | } |
778 | 779 | ||
779 | data->capabilities.interface_capabilities = buffer[4]; | 780 | data->capabilities.interface_capabilities = buffer[4]; |
@@ -781,8 +782,9 @@ static int get_capabilities(struct usbtmc_device_data *data) | |||
781 | data->capabilities.usb488_interface_capabilities = buffer[14]; | 782 | data->capabilities.usb488_interface_capabilities = buffer[14]; |
782 | data->capabilities.usb488_device_capabilities = buffer[15]; | 783 | data->capabilities.usb488_device_capabilities = buffer[15]; |
783 | 784 | ||
785 | err_out: | ||
784 | kfree(buffer); | 786 | kfree(buffer); |
785 | return 0; | 787 | return rv; |
786 | } | 788 | } |
787 | 789 | ||
788 | #define capability_attribute(name) \ | 790 | #define capability_attribute(name) \ |
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 69280c35b5cb..ad925946f869 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig | |||
@@ -28,7 +28,7 @@ comment "Miscellaneous USB options" | |||
28 | depends on USB | 28 | depends on USB |
29 | 29 | ||
30 | config USB_DEVICEFS | 30 | config USB_DEVICEFS |
31 | bool "USB device filesystem (DEPRECATED)" if EMBEDDED | 31 | bool "USB device filesystem (DEPRECATED)" |
32 | depends on USB | 32 | depends on USB |
33 | ---help--- | 33 | ---help--- |
34 | If you say Y here (and to "/proc file system support" in the "File | 34 | If you say Y here (and to "/proc file system support" in the "File |
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 73c108d117b4..96f11715cd26 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c | |||
@@ -136,17 +136,19 @@ static const struct class_info clas_info[] = | |||
136 | {USB_CLASS_AUDIO, "audio"}, | 136 | {USB_CLASS_AUDIO, "audio"}, |
137 | {USB_CLASS_COMM, "comm."}, | 137 | {USB_CLASS_COMM, "comm."}, |
138 | {USB_CLASS_HID, "HID"}, | 138 | {USB_CLASS_HID, "HID"}, |
139 | {USB_CLASS_HUB, "hub"}, | ||
140 | {USB_CLASS_PHYSICAL, "PID"}, | 139 | {USB_CLASS_PHYSICAL, "PID"}, |
140 | {USB_CLASS_STILL_IMAGE, "still"}, | ||
141 | {USB_CLASS_PRINTER, "print"}, | 141 | {USB_CLASS_PRINTER, "print"}, |
142 | {USB_CLASS_MASS_STORAGE, "stor."}, | 142 | {USB_CLASS_MASS_STORAGE, "stor."}, |
143 | {USB_CLASS_HUB, "hub"}, | ||
143 | {USB_CLASS_CDC_DATA, "data"}, | 144 | {USB_CLASS_CDC_DATA, "data"}, |
144 | {USB_CLASS_APP_SPEC, "app."}, | ||
145 | {USB_CLASS_VENDOR_SPEC, "vend."}, | ||
146 | {USB_CLASS_STILL_IMAGE, "still"}, | ||
147 | {USB_CLASS_CSCID, "scard"}, | 145 | {USB_CLASS_CSCID, "scard"}, |
148 | {USB_CLASS_CONTENT_SEC, "c-sec"}, | 146 | {USB_CLASS_CONTENT_SEC, "c-sec"}, |
149 | {USB_CLASS_VIDEO, "video"}, | 147 | {USB_CLASS_VIDEO, "video"}, |
148 | {USB_CLASS_WIRELESS_CONTROLLER, "wlcon"}, | ||
149 | {USB_CLASS_MISC, "misc"}, | ||
150 | {USB_CLASS_APP_SPEC, "app."}, | ||
151 | {USB_CLASS_VENDOR_SPEC, "vend."}, | ||
150 | {-1, "unk."} /* leave as last */ | 152 | {-1, "unk."} /* leave as last */ |
151 | }; | 153 | }; |
152 | 154 | ||
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 308609039c73..38b8bce782d6 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -325,21 +325,34 @@ static void async_completed(struct urb *urb) | |||
325 | struct async *as = urb->context; | 325 | struct async *as = urb->context; |
326 | struct dev_state *ps = as->ps; | 326 | struct dev_state *ps = as->ps; |
327 | struct siginfo sinfo; | 327 | struct siginfo sinfo; |
328 | struct pid *pid = NULL; | ||
329 | uid_t uid = 0; | ||
330 | uid_t euid = 0; | ||
331 | u32 secid = 0; | ||
332 | int signr; | ||
328 | 333 | ||
329 | spin_lock(&ps->lock); | 334 | spin_lock(&ps->lock); |
330 | list_move_tail(&as->asynclist, &ps->async_completed); | 335 | list_move_tail(&as->asynclist, &ps->async_completed); |
331 | spin_unlock(&ps->lock); | ||
332 | as->status = urb->status; | 336 | as->status = urb->status; |
333 | if (as->signr) { | 337 | signr = as->signr; |
338 | if (signr) { | ||
334 | sinfo.si_signo = as->signr; | 339 | sinfo.si_signo = as->signr; |
335 | sinfo.si_errno = as->status; | 340 | sinfo.si_errno = as->status; |
336 | sinfo.si_code = SI_ASYNCIO; | 341 | sinfo.si_code = SI_ASYNCIO; |
337 | sinfo.si_addr = as->userurb; | 342 | sinfo.si_addr = as->userurb; |
338 | kill_pid_info_as_uid(as->signr, &sinfo, as->pid, as->uid, | 343 | pid = as->pid; |
339 | as->euid, as->secid); | 344 | uid = as->uid; |
345 | euid = as->euid; | ||
346 | secid = as->secid; | ||
340 | } | 347 | } |
341 | snoop(&urb->dev->dev, "urb complete\n"); | 348 | snoop(&urb->dev->dev, "urb complete\n"); |
342 | snoop_urb(urb, as->userurb); | 349 | snoop_urb(urb, as->userurb); |
350 | spin_unlock(&ps->lock); | ||
351 | |||
352 | if (signr) | ||
353 | kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid, | ||
354 | euid, secid); | ||
355 | |||
343 | wake_up(&ps->wait); | 356 | wake_up(&ps->wait); |
344 | } | 357 | } |
345 | 358 | ||
@@ -982,7 +995,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
982 | USBDEVFS_URB_ZERO_PACKET | | 995 | USBDEVFS_URB_ZERO_PACKET | |
983 | USBDEVFS_URB_NO_INTERRUPT)) | 996 | USBDEVFS_URB_NO_INTERRUPT)) |
984 | return -EINVAL; | 997 | return -EINVAL; |
985 | if (!uurb->buffer) | 998 | if (uurb->buffer_length > 0 && !uurb->buffer) |
986 | return -EINVAL; | 999 | return -EINVAL; |
987 | if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && | 1000 | if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && |
988 | (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { | 1001 | (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { |
@@ -1038,11 +1051,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1038 | is_in = 0; | 1051 | is_in = 0; |
1039 | uurb->endpoint &= ~USB_DIR_IN; | 1052 | uurb->endpoint &= ~USB_DIR_IN; |
1040 | } | 1053 | } |
1041 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | ||
1042 | uurb->buffer, uurb->buffer_length)) { | ||
1043 | kfree(dr); | ||
1044 | return -EFAULT; | ||
1045 | } | ||
1046 | snoop(&ps->dev->dev, "control urb: bRequest=%02x " | 1054 | snoop(&ps->dev->dev, "control urb: bRequest=%02x " |
1047 | "bRrequestType=%02x wValue=%04x " | 1055 | "bRrequestType=%02x wValue=%04x " |
1048 | "wIndex=%04x wLength=%04x\n", | 1056 | "wIndex=%04x wLength=%04x\n", |
@@ -1062,9 +1070,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1062 | uurb->number_of_packets = 0; | 1070 | uurb->number_of_packets = 0; |
1063 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) | 1071 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) |
1064 | return -EINVAL; | 1072 | return -EINVAL; |
1065 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | ||
1066 | uurb->buffer, uurb->buffer_length)) | ||
1067 | return -EFAULT; | ||
1068 | snoop(&ps->dev->dev, "bulk urb\n"); | 1073 | snoop(&ps->dev->dev, "bulk urb\n"); |
1069 | break; | 1074 | break; |
1070 | 1075 | ||
@@ -1106,28 +1111,35 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1106 | return -EINVAL; | 1111 | return -EINVAL; |
1107 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) | 1112 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) |
1108 | return -EINVAL; | 1113 | return -EINVAL; |
1109 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | ||
1110 | uurb->buffer, uurb->buffer_length)) | ||
1111 | return -EFAULT; | ||
1112 | snoop(&ps->dev->dev, "interrupt urb\n"); | 1114 | snoop(&ps->dev->dev, "interrupt urb\n"); |
1113 | break; | 1115 | break; |
1114 | 1116 | ||
1115 | default: | 1117 | default: |
1116 | return -EINVAL; | 1118 | return -EINVAL; |
1117 | } | 1119 | } |
1118 | as = alloc_async(uurb->number_of_packets); | 1120 | if (uurb->buffer_length > 0 && |
1119 | if (!as) { | 1121 | !access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, |
1122 | uurb->buffer, uurb->buffer_length)) { | ||
1120 | kfree(isopkt); | 1123 | kfree(isopkt); |
1121 | kfree(dr); | 1124 | kfree(dr); |
1122 | return -ENOMEM; | 1125 | return -EFAULT; |
1123 | } | 1126 | } |
1124 | as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL); | 1127 | as = alloc_async(uurb->number_of_packets); |
1125 | if (!as->urb->transfer_buffer) { | 1128 | if (!as) { |
1126 | kfree(isopkt); | 1129 | kfree(isopkt); |
1127 | kfree(dr); | 1130 | kfree(dr); |
1128 | free_async(as); | ||
1129 | return -ENOMEM; | 1131 | return -ENOMEM; |
1130 | } | 1132 | } |
1133 | if (uurb->buffer_length > 0) { | ||
1134 | as->urb->transfer_buffer = kmalloc(uurb->buffer_length, | ||
1135 | GFP_KERNEL); | ||
1136 | if (!as->urb->transfer_buffer) { | ||
1137 | kfree(isopkt); | ||
1138 | kfree(dr); | ||
1139 | free_async(as); | ||
1140 | return -ENOMEM; | ||
1141 | } | ||
1142 | } | ||
1131 | as->urb->dev = ps->dev; | 1143 | as->urb->dev = ps->dev; |
1132 | as->urb->pipe = (uurb->type << 30) | | 1144 | as->urb->pipe = (uurb->type << 30) | |
1133 | __create_pipe(ps->dev, uurb->endpoint & 0xf) | | 1145 | __create_pipe(ps->dev, uurb->endpoint & 0xf) | |
@@ -1169,7 +1181,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1169 | kfree(isopkt); | 1181 | kfree(isopkt); |
1170 | as->ps = ps; | 1182 | as->ps = ps; |
1171 | as->userurb = arg; | 1183 | as->userurb = arg; |
1172 | if (uurb->endpoint & USB_DIR_IN) | 1184 | if (is_in && uurb->buffer_length > 0) |
1173 | as->userbuffer = uurb->buffer; | 1185 | as->userbuffer = uurb->buffer; |
1174 | else | 1186 | else |
1175 | as->userbuffer = NULL; | 1187 | as->userbuffer = NULL; |
@@ -1179,9 +1191,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1179 | as->uid = cred->uid; | 1191 | as->uid = cred->uid; |
1180 | as->euid = cred->euid; | 1192 | as->euid = cred->euid; |
1181 | security_task_getsecid(current, &as->secid); | 1193 | security_task_getsecid(current, &as->secid); |
1182 | if (!is_in) { | 1194 | if (!is_in && uurb->buffer_length > 0) { |
1183 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, | 1195 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, |
1184 | as->urb->transfer_buffer_length)) { | 1196 | uurb->buffer_length)) { |
1185 | free_async(as); | 1197 | free_async(as); |
1186 | return -EFAULT; | 1198 | return -EFAULT; |
1187 | } | 1199 | } |
@@ -1231,22 +1243,22 @@ static int processcompl(struct async *as, void __user * __user *arg) | |||
1231 | if (as->userbuffer) | 1243 | if (as->userbuffer) |
1232 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, | 1244 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, |
1233 | urb->transfer_buffer_length)) | 1245 | urb->transfer_buffer_length)) |
1234 | return -EFAULT; | 1246 | goto err_out; |
1235 | if (put_user(as->status, &userurb->status)) | 1247 | if (put_user(as->status, &userurb->status)) |
1236 | return -EFAULT; | 1248 | goto err_out; |
1237 | if (put_user(urb->actual_length, &userurb->actual_length)) | 1249 | if (put_user(urb->actual_length, &userurb->actual_length)) |
1238 | return -EFAULT; | 1250 | goto err_out; |
1239 | if (put_user(urb->error_count, &userurb->error_count)) | 1251 | if (put_user(urb->error_count, &userurb->error_count)) |
1240 | return -EFAULT; | 1252 | goto err_out; |
1241 | 1253 | ||
1242 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { | 1254 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { |
1243 | for (i = 0; i < urb->number_of_packets; i++) { | 1255 | for (i = 0; i < urb->number_of_packets; i++) { |
1244 | if (put_user(urb->iso_frame_desc[i].actual_length, | 1256 | if (put_user(urb->iso_frame_desc[i].actual_length, |
1245 | &userurb->iso_frame_desc[i].actual_length)) | 1257 | &userurb->iso_frame_desc[i].actual_length)) |
1246 | return -EFAULT; | 1258 | goto err_out; |
1247 | if (put_user(urb->iso_frame_desc[i].status, | 1259 | if (put_user(urb->iso_frame_desc[i].status, |
1248 | &userurb->iso_frame_desc[i].status)) | 1260 | &userurb->iso_frame_desc[i].status)) |
1249 | return -EFAULT; | 1261 | goto err_out; |
1250 | } | 1262 | } |
1251 | } | 1263 | } |
1252 | 1264 | ||
@@ -1255,6 +1267,10 @@ static int processcompl(struct async *as, void __user * __user *arg) | |||
1255 | if (put_user(addr, (void __user * __user *)arg)) | 1267 | if (put_user(addr, (void __user * __user *)arg)) |
1256 | return -EFAULT; | 1268 | return -EFAULT; |
1257 | return 0; | 1269 | return 0; |
1270 | |||
1271 | err_out: | ||
1272 | free_async(as); | ||
1273 | return -EFAULT; | ||
1258 | } | 1274 | } |
1259 | 1275 | ||
1260 | static struct async *reap_as(struct dev_state *ps) | 1276 | static struct async *reap_as(struct dev_state *ps) |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index d397ecfd5b17..ec5c67ea07b7 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -227,6 +227,10 @@ struct hc_driver { | |||
227 | /* has a port been handed over to a companion? */ | 227 | /* has a port been handed over to a companion? */ |
228 | int (*port_handed_over)(struct usb_hcd *, int); | 228 | int (*port_handed_over)(struct usb_hcd *, int); |
229 | 229 | ||
230 | /* CLEAR_TT_BUFFER completion callback */ | ||
231 | void (*clear_tt_buffer_complete)(struct usb_hcd *, | ||
232 | struct usb_host_endpoint *); | ||
233 | |||
230 | /* xHCI specific functions */ | 234 | /* xHCI specific functions */ |
231 | /* Called by usb_alloc_dev to alloc HC device structures */ | 235 | /* Called by usb_alloc_dev to alloc HC device structures */ |
232 | int (*alloc_dev)(struct usb_hcd *, struct usb_device *); | 236 | int (*alloc_dev)(struct usb_hcd *, struct usb_device *); |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 2af3b4f06054..71f86c60d83c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -450,10 +450,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) | |||
450 | * talking to TTs must queue control transfers (not just bulk and iso), so | 450 | * talking to TTs must queue control transfers (not just bulk and iso), so |
451 | * both can talk to the same hub concurrently. | 451 | * both can talk to the same hub concurrently. |
452 | */ | 452 | */ |
453 | static void hub_tt_kevent (struct work_struct *work) | 453 | static void hub_tt_work(struct work_struct *work) |
454 | { | 454 | { |
455 | struct usb_hub *hub = | 455 | struct usb_hub *hub = |
456 | container_of(work, struct usb_hub, tt.kevent); | 456 | container_of(work, struct usb_hub, tt.clear_work); |
457 | unsigned long flags; | 457 | unsigned long flags; |
458 | int limit = 100; | 458 | int limit = 100; |
459 | 459 | ||
@@ -462,6 +462,7 @@ static void hub_tt_kevent (struct work_struct *work) | |||
462 | struct list_head *next; | 462 | struct list_head *next; |
463 | struct usb_tt_clear *clear; | 463 | struct usb_tt_clear *clear; |
464 | struct usb_device *hdev = hub->hdev; | 464 | struct usb_device *hdev = hub->hdev; |
465 | const struct hc_driver *drv; | ||
465 | int status; | 466 | int status; |
466 | 467 | ||
467 | next = hub->tt.clear_list.next; | 468 | next = hub->tt.clear_list.next; |
@@ -471,21 +472,25 @@ static void hub_tt_kevent (struct work_struct *work) | |||
471 | /* drop lock so HCD can concurrently report other TT errors */ | 472 | /* drop lock so HCD can concurrently report other TT errors */ |
472 | spin_unlock_irqrestore (&hub->tt.lock, flags); | 473 | spin_unlock_irqrestore (&hub->tt.lock, flags); |
473 | status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt); | 474 | status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt); |
474 | spin_lock_irqsave (&hub->tt.lock, flags); | ||
475 | |||
476 | if (status) | 475 | if (status) |
477 | dev_err (&hdev->dev, | 476 | dev_err (&hdev->dev, |
478 | "clear tt %d (%04x) error %d\n", | 477 | "clear tt %d (%04x) error %d\n", |
479 | clear->tt, clear->devinfo, status); | 478 | clear->tt, clear->devinfo, status); |
479 | |||
480 | /* Tell the HCD, even if the operation failed */ | ||
481 | drv = clear->hcd->driver; | ||
482 | if (drv->clear_tt_buffer_complete) | ||
483 | (drv->clear_tt_buffer_complete)(clear->hcd, clear->ep); | ||
484 | |||
480 | kfree(clear); | 485 | kfree(clear); |
486 | spin_lock_irqsave(&hub->tt.lock, flags); | ||
481 | } | 487 | } |
482 | spin_unlock_irqrestore (&hub->tt.lock, flags); | 488 | spin_unlock_irqrestore (&hub->tt.lock, flags); |
483 | } | 489 | } |
484 | 490 | ||
485 | /** | 491 | /** |
486 | * usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub | 492 | * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub |
487 | * @udev: the device whose split transaction failed | 493 | * @urb: an URB associated with the failed or incomplete split transaction |
488 | * @pipe: identifies the endpoint of the failed transaction | ||
489 | * | 494 | * |
490 | * High speed HCDs use this to tell the hub driver that some split control or | 495 | * High speed HCDs use this to tell the hub driver that some split control or |
491 | * bulk transaction failed in a way that requires clearing internal state of | 496 | * bulk transaction failed in a way that requires clearing internal state of |
@@ -495,8 +500,10 @@ static void hub_tt_kevent (struct work_struct *work) | |||
495 | * It may not be possible for that hub to handle additional full (or low) | 500 | * It may not be possible for that hub to handle additional full (or low) |
496 | * speed transactions until that state is fully cleared out. | 501 | * speed transactions until that state is fully cleared out. |
497 | */ | 502 | */ |
498 | void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) | 503 | int usb_hub_clear_tt_buffer(struct urb *urb) |
499 | { | 504 | { |
505 | struct usb_device *udev = urb->dev; | ||
506 | int pipe = urb->pipe; | ||
500 | struct usb_tt *tt = udev->tt; | 507 | struct usb_tt *tt = udev->tt; |
501 | unsigned long flags; | 508 | unsigned long flags; |
502 | struct usb_tt_clear *clear; | 509 | struct usb_tt_clear *clear; |
@@ -508,7 +515,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) | |||
508 | if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) { | 515 | if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) { |
509 | dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n"); | 516 | dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n"); |
510 | /* FIXME recover somehow ... RESET_TT? */ | 517 | /* FIXME recover somehow ... RESET_TT? */ |
511 | return; | 518 | return -ENOMEM; |
512 | } | 519 | } |
513 | 520 | ||
514 | /* info that CLEAR_TT_BUFFER needs */ | 521 | /* info that CLEAR_TT_BUFFER needs */ |
@@ -520,14 +527,19 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) | |||
520 | : (USB_ENDPOINT_XFER_BULK << 11); | 527 | : (USB_ENDPOINT_XFER_BULK << 11); |
521 | if (usb_pipein (pipe)) | 528 | if (usb_pipein (pipe)) |
522 | clear->devinfo |= 1 << 15; | 529 | clear->devinfo |= 1 << 15; |
523 | 530 | ||
531 | /* info for completion callback */ | ||
532 | clear->hcd = bus_to_hcd(udev->bus); | ||
533 | clear->ep = urb->ep; | ||
534 | |||
524 | /* tell keventd to clear state for this TT */ | 535 | /* tell keventd to clear state for this TT */ |
525 | spin_lock_irqsave (&tt->lock, flags); | 536 | spin_lock_irqsave (&tt->lock, flags); |
526 | list_add_tail (&clear->clear_list, &tt->clear_list); | 537 | list_add_tail (&clear->clear_list, &tt->clear_list); |
527 | schedule_work (&tt->kevent); | 538 | schedule_work(&tt->clear_work); |
528 | spin_unlock_irqrestore (&tt->lock, flags); | 539 | spin_unlock_irqrestore (&tt->lock, flags); |
540 | return 0; | ||
529 | } | 541 | } |
530 | EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer); | 542 | EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer); |
531 | 543 | ||
532 | /* If do_delay is false, return the number of milliseconds the caller | 544 | /* If do_delay is false, return the number of milliseconds the caller |
533 | * needs to delay. | 545 | * needs to delay. |
@@ -818,7 +830,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) | |||
818 | if (hub->has_indicators) | 830 | if (hub->has_indicators) |
819 | cancel_delayed_work_sync(&hub->leds); | 831 | cancel_delayed_work_sync(&hub->leds); |
820 | if (hub->tt.hub) | 832 | if (hub->tt.hub) |
821 | cancel_work_sync(&hub->tt.kevent); | 833 | cancel_work_sync(&hub->tt.clear_work); |
822 | } | 834 | } |
823 | 835 | ||
824 | /* caller has locked the hub device */ | 836 | /* caller has locked the hub device */ |
@@ -935,7 +947,7 @@ static int hub_configure(struct usb_hub *hub, | |||
935 | 947 | ||
936 | spin_lock_init (&hub->tt.lock); | 948 | spin_lock_init (&hub->tt.lock); |
937 | INIT_LIST_HEAD (&hub->tt.clear_list); | 949 | INIT_LIST_HEAD (&hub->tt.clear_list); |
938 | INIT_WORK (&hub->tt.kevent, hub_tt_kevent); | 950 | INIT_WORK(&hub->tt.clear_work, hub_tt_work); |
939 | switch (hdev->descriptor.bDeviceProtocol) { | 951 | switch (hdev->descriptor.bDeviceProtocol) { |
940 | case 0: | 952 | case 0: |
941 | break; | 953 | break; |
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 889c0f32a40b..de8081f065ed 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h | |||
@@ -188,16 +188,18 @@ struct usb_tt { | |||
188 | /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ | 188 | /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ |
189 | spinlock_t lock; | 189 | spinlock_t lock; |
190 | struct list_head clear_list; /* of usb_tt_clear */ | 190 | struct list_head clear_list; /* of usb_tt_clear */ |
191 | struct work_struct kevent; | 191 | struct work_struct clear_work; |
192 | }; | 192 | }; |
193 | 193 | ||
194 | struct usb_tt_clear { | 194 | struct usb_tt_clear { |
195 | struct list_head clear_list; | 195 | struct list_head clear_list; |
196 | unsigned tt; | 196 | unsigned tt; |
197 | u16 devinfo; | 197 | u16 devinfo; |
198 | struct usb_hcd *hcd; | ||
199 | struct usb_host_endpoint *ep; | ||
198 | }; | 200 | }; |
199 | 201 | ||
200 | extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe); | 202 | extern int usb_hub_clear_tt_buffer(struct urb *urb); |
201 | extern void usb_ep0_reinit(struct usb_device *); | 203 | extern void usb_ep0_reinit(struct usb_device *); |
202 | 204 | ||
203 | #endif /* __LINUX_HUB_H */ | 205 | #endif /* __LINUX_HUB_H */ |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 2bed83caacb1..9720e699f472 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -806,6 +806,48 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid, | |||
806 | return rc; | 806 | return rc; |
807 | } | 807 | } |
808 | 808 | ||
809 | static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf) | ||
810 | { | ||
811 | int err; | ||
812 | |||
813 | if (dev->have_langid) | ||
814 | return 0; | ||
815 | |||
816 | if (dev->string_langid < 0) | ||
817 | return -EPIPE; | ||
818 | |||
819 | err = usb_string_sub(dev, 0, 0, tbuf); | ||
820 | |||
821 | /* If the string was reported but is malformed, default to english | ||
822 | * (0x0409) */ | ||
823 | if (err == -ENODATA || (err > 0 && err < 4)) { | ||
824 | dev->string_langid = 0x0409; | ||
825 | dev->have_langid = 1; | ||
826 | dev_err(&dev->dev, | ||
827 | "string descriptor 0 malformed (err = %d), " | ||
828 | "defaulting to 0x%04x\n", | ||
829 | err, dev->string_langid); | ||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | /* In case of all other errors, we assume the device is not able to | ||
834 | * deal with strings at all. Set string_langid to -1 in order to | ||
835 | * prevent any string to be retrieved from the device */ | ||
836 | if (err < 0) { | ||
837 | dev_err(&dev->dev, "string descriptor 0 read error: %d\n", | ||
838 | err); | ||
839 | dev->string_langid = -1; | ||
840 | return -EPIPE; | ||
841 | } | ||
842 | |||
843 | /* always use the first langid listed */ | ||
844 | dev->string_langid = tbuf[2] | (tbuf[3] << 8); | ||
845 | dev->have_langid = 1; | ||
846 | dev_dbg(&dev->dev, "default language 0x%04x\n", | ||
847 | dev->string_langid); | ||
848 | return 0; | ||
849 | } | ||
850 | |||
809 | /** | 851 | /** |
810 | * usb_string - returns UTF-8 version of a string descriptor | 852 | * usb_string - returns UTF-8 version of a string descriptor |
811 | * @dev: the device whose string descriptor is being retrieved | 853 | * @dev: the device whose string descriptor is being retrieved |
@@ -837,24 +879,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) | |||
837 | if (!tbuf) | 879 | if (!tbuf) |
838 | return -ENOMEM; | 880 | return -ENOMEM; |
839 | 881 | ||
840 | /* get langid for strings if it's not yet known */ | 882 | err = usb_get_langid(dev, tbuf); |
841 | if (!dev->have_langid) { | 883 | if (err < 0) |
842 | err = usb_string_sub(dev, 0, 0, tbuf); | 884 | goto errout; |
843 | if (err < 0) { | ||
844 | dev_err(&dev->dev, | ||
845 | "string descriptor 0 read error: %d\n", | ||
846 | err); | ||
847 | } else if (err < 4) { | ||
848 | dev_err(&dev->dev, "string descriptor 0 too short\n"); | ||
849 | } else { | ||
850 | dev->string_langid = tbuf[2] | (tbuf[3] << 8); | ||
851 | /* always use the first langid listed */ | ||
852 | dev_dbg(&dev->dev, "default language 0x%04x\n", | ||
853 | dev->string_langid); | ||
854 | } | ||
855 | |||
856 | dev->have_langid = 1; | ||
857 | } | ||
858 | 885 | ||
859 | err = usb_string_sub(dev, dev->string_langid, index, tbuf); | 886 | err = usb_string_sub(dev, dev->string_langid, index, tbuf); |
860 | if (err < 0) | 887 | if (err < 0) |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 5d1ddf485d1e..7f8e83a954ac 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -286,6 +286,27 @@ config USB_S3C_HSOTG | |||
286 | default USB_GADGET | 286 | default USB_GADGET |
287 | select USB_GADGET_SELECTED | 287 | select USB_GADGET_SELECTED |
288 | 288 | ||
289 | config USB_GADGET_IMX | ||
290 | boolean "Freescale IMX USB Peripheral Controller" | ||
291 | depends on ARCH_MX1 | ||
292 | help | ||
293 | Freescale's IMX series include an integrated full speed | ||
294 | USB 1.1 device controller. The controller in the IMX series | ||
295 | is register-compatible. | ||
296 | |||
297 | It has Six fixed-function endpoints, as well as endpoint | ||
298 | zero (for control transfers). | ||
299 | |||
300 | Say "y" to link the driver statically, or "m" to build a | ||
301 | dynamically linked module called "imx_udc" and force all | ||
302 | gadget drivers to also be dynamically linked. | ||
303 | |||
304 | config USB_IMX | ||
305 | tristate | ||
306 | depends on USB_GADGET_IMX | ||
307 | default USB_GADGET | ||
308 | select USB_GADGET_SELECTED | ||
309 | |||
289 | config USB_GADGET_S3C2410 | 310 | config USB_GADGET_S3C2410 |
290 | boolean "S3C2410 USB Device Controller" | 311 | boolean "S3C2410 USB Device Controller" |
291 | depends on ARCH_S3C2410 | 312 | depends on ARCH_S3C2410 |
@@ -321,27 +342,6 @@ config USB_GADGET_MUSB_HDRC | |||
321 | This OTG-capable silicon IP is used in dual designs including | 342 | This OTG-capable silicon IP is used in dual designs including |
322 | the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin | 343 | the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin |
323 | 344 | ||
324 | config USB_GADGET_IMX | ||
325 | boolean "Freescale IMX USB Peripheral Controller" | ||
326 | depends on ARCH_MX1 | ||
327 | help | ||
328 | Freescale's IMX series include an integrated full speed | ||
329 | USB 1.1 device controller. The controller in the IMX series | ||
330 | is register-compatible. | ||
331 | |||
332 | It has Six fixed-function endpoints, as well as endpoint | ||
333 | zero (for control transfers). | ||
334 | |||
335 | Say "y" to link the driver statically, or "m" to build a | ||
336 | dynamically linked module called "imx_udc" and force all | ||
337 | gadget drivers to also be dynamically linked. | ||
338 | |||
339 | config USB_IMX | ||
340 | tristate | ||
341 | depends on USB_GADGET_IMX | ||
342 | default USB_GADGET | ||
343 | select USB_GADGET_SELECTED | ||
344 | |||
345 | config USB_GADGET_M66592 | 345 | config USB_GADGET_M66592 |
346 | boolean "Renesas M66592 USB Peripheral Controller" | 346 | boolean "Renesas M66592 USB Peripheral Controller" |
347 | select USB_GADGET_DUALSPEED | 347 | select USB_GADGET_DUALSPEED |
@@ -604,6 +604,7 @@ config USB_ZERO_HNPTEST | |||
604 | config USB_AUDIO | 604 | config USB_AUDIO |
605 | tristate "Audio Gadget (EXPERIMENTAL)" | 605 | tristate "Audio Gadget (EXPERIMENTAL)" |
606 | depends on SND | 606 | depends on SND |
607 | select SND_PCM | ||
607 | help | 608 | help |
608 | Gadget Audio is compatible with USB Audio Class specification 1.0. | 609 | Gadget Audio is compatible with USB Audio Class specification 1.0. |
609 | It will include at least one AudioControl interface, zero or more | 610 | It will include at least one AudioControl interface, zero or more |
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 94de7e864614..9f80f4e970bd 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c | |||
@@ -42,9 +42,9 @@ | |||
42 | * Instead: allocate your own, using normal USB-IF procedures. | 42 | * Instead: allocate your own, using normal USB-IF procedures. |
43 | */ | 43 | */ |
44 | 44 | ||
45 | /* Thanks to NetChip Technologies for donating this product ID. */ | 45 | /* Thanks to Linux Foundation for donating this product ID. */ |
46 | #define AUDIO_VENDOR_NUM 0x0525 /* NetChip */ | 46 | #define AUDIO_VENDOR_NUM 0x1d6b /* Linux Foundation */ |
47 | #define AUDIO_PRODUCT_NUM 0xa4a1 /* Linux-USB Audio Gadget */ | 47 | #define AUDIO_PRODUCT_NUM 0x0101 /* Linux-USB Audio Gadget */ |
48 | 48 | ||
49 | /*-------------------------------------------------------------------------*/ | 49 | /*-------------------------------------------------------------------------*/ |
50 | 50 | ||
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index d006dc652e02..bd102f5052ba 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -293,15 +293,16 @@ static int __init eth_bind(struct usb_composite_dev *cdev) | |||
293 | /* CDC Subset */ | 293 | /* CDC Subset */ |
294 | eth_config_driver.label = "CDC Subset/SAFE"; | 294 | eth_config_driver.label = "CDC Subset/SAFE"; |
295 | 295 | ||
296 | device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM), | 296 | device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM); |
297 | device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM), | 297 | device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM); |
298 | device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; | 298 | if (!has_rndis()) |
299 | device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; | ||
299 | } | 300 | } |
300 | 301 | ||
301 | if (has_rndis()) { | 302 | if (has_rndis()) { |
302 | /* RNDIS plus ECM-or-Subset */ | 303 | /* RNDIS plus ECM-or-Subset */ |
303 | device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM), | 304 | device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM); |
304 | device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM), | 305 | device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM); |
305 | device_desc.bNumConfigurations = 2; | 306 | device_desc.bNumConfigurations = 2; |
306 | } | 307 | } |
307 | 308 | ||
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 0ce4e2819847..ed21e263f832 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c | |||
@@ -139,7 +139,7 @@ static int is_vbus_present(void) | |||
139 | { | 139 | { |
140 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | 140 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; |
141 | 141 | ||
142 | if (mach->gpio_vbus) { | 142 | if (gpio_is_valid(mach->gpio_vbus)) { |
143 | int value = gpio_get_value(mach->gpio_vbus); | 143 | int value = gpio_get_value(mach->gpio_vbus); |
144 | 144 | ||
145 | if (mach->gpio_vbus_inverted) | 145 | if (mach->gpio_vbus_inverted) |
@@ -158,7 +158,7 @@ static void pullup_off(void) | |||
158 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | 158 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; |
159 | int off_level = mach->gpio_pullup_inverted; | 159 | int off_level = mach->gpio_pullup_inverted; |
160 | 160 | ||
161 | if (mach->gpio_pullup) | 161 | if (gpio_is_valid(mach->gpio_pullup)) |
162 | gpio_set_value(mach->gpio_pullup, off_level); | 162 | gpio_set_value(mach->gpio_pullup, off_level); |
163 | else if (mach->udc_command) | 163 | else if (mach->udc_command) |
164 | mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); | 164 | mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); |
@@ -169,7 +169,7 @@ static void pullup_on(void) | |||
169 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | 169 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; |
170 | int on_level = !mach->gpio_pullup_inverted; | 170 | int on_level = !mach->gpio_pullup_inverted; |
171 | 171 | ||
172 | if (mach->gpio_pullup) | 172 | if (gpio_is_valid(mach->gpio_pullup)) |
173 | gpio_set_value(mach->gpio_pullup, on_level); | 173 | gpio_set_value(mach->gpio_pullup, on_level); |
174 | else if (mach->udc_command) | 174 | else if (mach->udc_command) |
175 | mach->udc_command(PXA2XX_UDC_CMD_CONNECT); | 175 | mach->udc_command(PXA2XX_UDC_CMD_CONNECT); |
@@ -1000,7 +1000,7 @@ static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active) | |||
1000 | udc = container_of(_gadget, struct pxa25x_udc, gadget); | 1000 | udc = container_of(_gadget, struct pxa25x_udc, gadget); |
1001 | 1001 | ||
1002 | /* not all boards support pullup control */ | 1002 | /* not all boards support pullup control */ |
1003 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) | 1003 | if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command) |
1004 | return -EOPNOTSUPP; | 1004 | return -EOPNOTSUPP; |
1005 | 1005 | ||
1006 | udc->pullup = (is_active != 0); | 1006 | udc->pullup = (is_active != 0); |
@@ -1802,11 +1802,13 @@ pxa25x_udc_irq(int irq, void *_dev) | |||
1802 | USIR0 |= tmp; | 1802 | USIR0 |= tmp; |
1803 | handled = 1; | 1803 | handled = 1; |
1804 | } | 1804 | } |
1805 | #ifndef CONFIG_USB_PXA25X_SMALL | ||
1805 | if (usir1 & tmp) { | 1806 | if (usir1 & tmp) { |
1806 | handle_ep(&dev->ep[i+8]); | 1807 | handle_ep(&dev->ep[i+8]); |
1807 | USIR1 |= tmp; | 1808 | USIR1 |= tmp; |
1808 | handled = 1; | 1809 | handled = 1; |
1809 | } | 1810 | } |
1811 | #endif | ||
1810 | } | 1812 | } |
1811 | } | 1813 | } |
1812 | 1814 | ||
@@ -2160,7 +2162,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) | |||
2160 | dev->dev = &pdev->dev; | 2162 | dev->dev = &pdev->dev; |
2161 | dev->mach = pdev->dev.platform_data; | 2163 | dev->mach = pdev->dev.platform_data; |
2162 | 2164 | ||
2163 | if (dev->mach->gpio_vbus) { | 2165 | if (gpio_is_valid(dev->mach->gpio_vbus)) { |
2164 | if ((retval = gpio_request(dev->mach->gpio_vbus, | 2166 | if ((retval = gpio_request(dev->mach->gpio_vbus, |
2165 | "pxa25x_udc GPIO VBUS"))) { | 2167 | "pxa25x_udc GPIO VBUS"))) { |
2166 | dev_dbg(&pdev->dev, | 2168 | dev_dbg(&pdev->dev, |
@@ -2173,7 +2175,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) | |||
2173 | } else | 2175 | } else |
2174 | vbus_irq = 0; | 2176 | vbus_irq = 0; |
2175 | 2177 | ||
2176 | if (dev->mach->gpio_pullup) { | 2178 | if (gpio_is_valid(dev->mach->gpio_pullup)) { |
2177 | if ((retval = gpio_request(dev->mach->gpio_pullup, | 2179 | if ((retval = gpio_request(dev->mach->gpio_pullup, |
2178 | "pca25x_udc GPIO PULLUP"))) { | 2180 | "pca25x_udc GPIO PULLUP"))) { |
2179 | dev_dbg(&pdev->dev, | 2181 | dev_dbg(&pdev->dev, |
@@ -2256,10 +2258,10 @@ lubbock_fail0: | |||
2256 | #endif | 2258 | #endif |
2257 | free_irq(irq, dev); | 2259 | free_irq(irq, dev); |
2258 | err_irq1: | 2260 | err_irq1: |
2259 | if (dev->mach->gpio_pullup) | 2261 | if (gpio_is_valid(dev->mach->gpio_pullup)) |
2260 | gpio_free(dev->mach->gpio_pullup); | 2262 | gpio_free(dev->mach->gpio_pullup); |
2261 | err_gpio_pullup: | 2263 | err_gpio_pullup: |
2262 | if (dev->mach->gpio_vbus) | 2264 | if (gpio_is_valid(dev->mach->gpio_vbus)) |
2263 | gpio_free(dev->mach->gpio_vbus); | 2265 | gpio_free(dev->mach->gpio_vbus); |
2264 | err_gpio_vbus: | 2266 | err_gpio_vbus: |
2265 | clk_put(dev->clk); | 2267 | clk_put(dev->clk); |
@@ -2294,11 +2296,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev) | |||
2294 | free_irq(LUBBOCK_USB_IRQ, dev); | 2296 | free_irq(LUBBOCK_USB_IRQ, dev); |
2295 | } | 2297 | } |
2296 | #endif | 2298 | #endif |
2297 | if (dev->mach->gpio_vbus) { | 2299 | if (gpio_is_valid(dev->mach->gpio_vbus)) { |
2298 | free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev); | 2300 | free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev); |
2299 | gpio_free(dev->mach->gpio_vbus); | 2301 | gpio_free(dev->mach->gpio_vbus); |
2300 | } | 2302 | } |
2301 | if (dev->mach->gpio_pullup) | 2303 | if (gpio_is_valid(dev->mach->gpio_pullup)) |
2302 | gpio_free(dev->mach->gpio_pullup); | 2304 | gpio_free(dev->mach->gpio_pullup); |
2303 | 2305 | ||
2304 | clk_put(dev->clk); | 2306 | clk_put(dev->clk); |
@@ -2329,7 +2331,7 @@ static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state) | |||
2329 | struct pxa25x_udc *udc = platform_get_drvdata(dev); | 2331 | struct pxa25x_udc *udc = platform_get_drvdata(dev); |
2330 | unsigned long flags; | 2332 | unsigned long flags; |
2331 | 2333 | ||
2332 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) | 2334 | if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command) |
2333 | WARNING("USB host won't detect disconnect!\n"); | 2335 | WARNING("USB host won't detect disconnect!\n"); |
2334 | udc->suspended = 1; | 2336 | udc->suspended = 1; |
2335 | 2337 | ||
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 2b4660e08c4d..ca41b0b5afb3 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c | |||
@@ -442,6 +442,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
442 | 442 | ||
443 | case OID_802_3_MAC_OPTIONS: | 443 | case OID_802_3_MAC_OPTIONS: |
444 | pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__); | 444 | pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__); |
445 | *outbuf = cpu_to_le32(0); | ||
446 | retval = 0; | ||
445 | break; | 447 | break; |
446 | 448 | ||
447 | /* ieee802.3 statistics OIDs (table 4-4) */ | 449 | /* ieee802.3 statistics OIDs (table 4-4) */ |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0c03471f0d41..1a920c70b5a1 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -181,26 +181,27 @@ config USB_OHCI_HCD_PPC_SOC | |||
181 | Enables support for the USB controller on the MPC52xx or | 181 | Enables support for the USB controller on the MPC52xx or |
182 | STB03xxx processor chip. If unsure, say Y. | 182 | STB03xxx processor chip. If unsure, say Y. |
183 | 183 | ||
184 | config USB_OHCI_HCD_PPC_OF | ||
185 | bool "OHCI support for PPC USB controller on OF platform bus" | ||
186 | depends on USB_OHCI_HCD && PPC_OF | ||
187 | default y | ||
188 | ---help--- | ||
189 | Enables support for the USB controller PowerPC present on the | ||
190 | OpenFirmware platform bus. | ||
191 | |||
192 | config USB_OHCI_HCD_PPC_OF_BE | 184 | config USB_OHCI_HCD_PPC_OF_BE |
193 | bool "Support big endian HC" | 185 | bool "OHCI support for OF platform bus (big endian)" |
194 | depends on USB_OHCI_HCD_PPC_OF | 186 | depends on USB_OHCI_HCD && PPC_OF |
195 | default y | ||
196 | select USB_OHCI_BIG_ENDIAN_DESC | 187 | select USB_OHCI_BIG_ENDIAN_DESC |
197 | select USB_OHCI_BIG_ENDIAN_MMIO | 188 | select USB_OHCI_BIG_ENDIAN_MMIO |
189 | ---help--- | ||
190 | Enables support for big-endian USB controllers present on the | ||
191 | OpenFirmware platform bus. | ||
198 | 192 | ||
199 | config USB_OHCI_HCD_PPC_OF_LE | 193 | config USB_OHCI_HCD_PPC_OF_LE |
200 | bool "Support little endian HC" | 194 | bool "OHCI support for OF platform bus (little endian)" |
201 | depends on USB_OHCI_HCD_PPC_OF | 195 | depends on USB_OHCI_HCD && PPC_OF |
202 | default n | ||
203 | select USB_OHCI_LITTLE_ENDIAN | 196 | select USB_OHCI_LITTLE_ENDIAN |
197 | ---help--- | ||
198 | Enables support for little-endian USB controllers present on the | ||
199 | OpenFirmware platform bus. | ||
200 | |||
201 | config USB_OHCI_HCD_PPC_OF | ||
202 | bool | ||
203 | depends on USB_OHCI_HCD && PPC_OF | ||
204 | default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE | ||
204 | 205 | ||
205 | config USB_OHCI_HCD_PCI | 206 | config USB_OHCI_HCD_PCI |
206 | bool "OHCI support for PCI-bus USB controllers" | 207 | bool "OHCI support for PCI-bus USB controllers" |
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index c3a778bd359c..59d208d94d4e 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c | |||
@@ -113,6 +113,8 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { | |||
113 | .bus_resume = ehci_bus_resume, | 113 | .bus_resume = ehci_bus_resume, |
114 | .relinquish_port = ehci_relinquish_port, | 114 | .relinquish_port = ehci_relinquish_port, |
115 | .port_handed_over = ehci_port_handed_over, | 115 | .port_handed_over = ehci_port_handed_over, |
116 | |||
117 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
116 | }; | 118 | }; |
117 | 119 | ||
118 | static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | 120 | static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index bf86809c5120..991174937db3 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -325,6 +325,8 @@ static const struct hc_driver ehci_fsl_hc_driver = { | |||
325 | .bus_resume = ehci_bus_resume, | 325 | .bus_resume = ehci_bus_resume, |
326 | .relinquish_port = ehci_relinquish_port, | 326 | .relinquish_port = ehci_relinquish_port, |
327 | .port_handed_over = ehci_port_handed_over, | 327 | .port_handed_over = ehci_port_handed_over, |
328 | |||
329 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
328 | }; | 330 | }; |
329 | 331 | ||
330 | static int ehci_fsl_drv_probe(struct platform_device *pdev) | 332 | static int ehci_fsl_drv_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 2b72473544d3..7d03549c3339 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1003,6 +1003,8 @@ idle_timeout: | |||
1003 | schedule_timeout_uninterruptible(1); | 1003 | schedule_timeout_uninterruptible(1); |
1004 | goto rescan; | 1004 | goto rescan; |
1005 | case QH_STATE_IDLE: /* fully unlinked */ | 1005 | case QH_STATE_IDLE: /* fully unlinked */ |
1006 | if (qh->clearing_tt) | ||
1007 | goto idle_timeout; | ||
1006 | if (list_empty (&qh->qtd_list)) { | 1008 | if (list_empty (&qh->qtd_list)) { |
1007 | qh_put (qh); | 1009 | qh_put (qh); |
1008 | break; | 1010 | break; |
@@ -1030,12 +1032,14 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) | |||
1030 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 1032 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
1031 | struct ehci_qh *qh; | 1033 | struct ehci_qh *qh; |
1032 | int eptype = usb_endpoint_type(&ep->desc); | 1034 | int eptype = usb_endpoint_type(&ep->desc); |
1035 | int epnum = usb_endpoint_num(&ep->desc); | ||
1036 | int is_out = usb_endpoint_dir_out(&ep->desc); | ||
1037 | unsigned long flags; | ||
1033 | 1038 | ||
1034 | if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) | 1039 | if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) |
1035 | return; | 1040 | return; |
1036 | 1041 | ||
1037 | rescan: | 1042 | spin_lock_irqsave(&ehci->lock, flags); |
1038 | spin_lock_irq(&ehci->lock); | ||
1039 | qh = ep->hcpriv; | 1043 | qh = ep->hcpriv; |
1040 | 1044 | ||
1041 | /* For Bulk and Interrupt endpoints we maintain the toggle state | 1045 | /* For Bulk and Interrupt endpoints we maintain the toggle state |
@@ -1044,29 +1048,24 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) | |||
1044 | * the toggle bit in the QH. | 1048 | * the toggle bit in the QH. |
1045 | */ | 1049 | */ |
1046 | if (qh) { | 1050 | if (qh) { |
1051 | usb_settoggle(qh->dev, epnum, is_out, 0); | ||
1047 | if (!list_empty(&qh->qtd_list)) { | 1052 | if (!list_empty(&qh->qtd_list)) { |
1048 | WARN_ONCE(1, "clear_halt for a busy endpoint\n"); | 1053 | WARN_ONCE(1, "clear_halt for a busy endpoint\n"); |
1049 | } else if (qh->qh_state == QH_STATE_IDLE) { | 1054 | } else if (qh->qh_state == QH_STATE_LINKED) { |
1050 | qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); | 1055 | |
1051 | } else { | 1056 | /* The toggle value in the QH can't be updated |
1052 | /* It's not safe to write into the overlay area | 1057 | * while the QH is active. Unlink it now; |
1053 | * while the QH is active. Unlink it first and | 1058 | * re-linking will call qh_refresh(). |
1054 | * wait for the unlink to complete. | ||
1055 | */ | 1059 | */ |
1056 | if (qh->qh_state == QH_STATE_LINKED) { | 1060 | if (eptype == USB_ENDPOINT_XFER_BULK) { |
1057 | if (eptype == USB_ENDPOINT_XFER_BULK) { | 1061 | unlink_async(ehci, qh); |
1058 | unlink_async(ehci, qh); | 1062 | } else { |
1059 | } else { | 1063 | intr_deschedule(ehci, qh); |
1060 | intr_deschedule(ehci, qh); | 1064 | (void) qh_schedule(ehci, qh); |
1061 | (void) qh_schedule(ehci, qh); | ||
1062 | } | ||
1063 | } | 1065 | } |
1064 | spin_unlock_irq(&ehci->lock); | ||
1065 | schedule_timeout_uninterruptible(1); | ||
1066 | goto rescan; | ||
1067 | } | 1066 | } |
1068 | } | 1067 | } |
1069 | spin_unlock_irq(&ehci->lock); | 1068 | spin_unlock_irqrestore(&ehci->lock, flags); |
1070 | } | 1069 | } |
1071 | 1070 | ||
1072 | static int ehci_get_frame (struct usb_hcd *hcd) | 1071 | static int ehci_get_frame (struct usb_hcd *hcd) |
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index a44bb4a94954..89b7c70c6ed6 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c | |||
@@ -61,6 +61,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = { | |||
61 | #endif | 61 | #endif |
62 | .relinquish_port = ehci_relinquish_port, | 62 | .relinquish_port = ehci_relinquish_port, |
63 | .port_handed_over = ehci_port_handed_over, | 63 | .port_handed_over = ehci_port_handed_over, |
64 | |||
65 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
64 | }; | 66 | }; |
65 | 67 | ||
66 | static int ixp4xx_ehci_probe(struct platform_device *pdev) | 68 | static int ixp4xx_ehci_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 770dd9aba62a..dc2ac613a9d1 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c | |||
@@ -165,6 +165,8 @@ static const struct hc_driver ehci_orion_hc_driver = { | |||
165 | .bus_resume = ehci_bus_resume, | 165 | .bus_resume = ehci_bus_resume, |
166 | .relinquish_port = ehci_relinquish_port, | 166 | .relinquish_port = ehci_relinquish_port, |
167 | .port_handed_over = ehci_port_handed_over, | 167 | .port_handed_over = ehci_port_handed_over, |
168 | |||
169 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
168 | }; | 170 | }; |
169 | 171 | ||
170 | static void __init | 172 | static void __init |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index f3683e1da161..c2f1b7df918c 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -404,6 +404,8 @@ static const struct hc_driver ehci_pci_hc_driver = { | |||
404 | .bus_resume = ehci_bus_resume, | 404 | .bus_resume = ehci_bus_resume, |
405 | .relinquish_port = ehci_relinquish_port, | 405 | .relinquish_port = ehci_relinquish_port, |
406 | .port_handed_over = ehci_port_handed_over, | 406 | .port_handed_over = ehci_port_handed_over, |
407 | |||
408 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
407 | }; | 409 | }; |
408 | 410 | ||
409 | /*-------------------------------------------------------------------------*/ | 411 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index fbd272288fc2..36f96da129f5 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c | |||
@@ -79,6 +79,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { | |||
79 | #endif | 79 | #endif |
80 | .relinquish_port = ehci_relinquish_port, | 80 | .relinquish_port = ehci_relinquish_port, |
81 | .port_handed_over = ehci_port_handed_over, | 81 | .port_handed_over = ehci_port_handed_over, |
82 | |||
83 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
82 | }; | 84 | }; |
83 | 85 | ||
84 | 86 | ||
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 93f7035d00a1..1dee33b9139e 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c | |||
@@ -75,6 +75,8 @@ static const struct hc_driver ps3_ehci_hc_driver = { | |||
75 | #endif | 75 | #endif |
76 | .relinquish_port = ehci_relinquish_port, | 76 | .relinquish_port = ehci_relinquish_port, |
77 | .port_handed_over = ehci_port_handed_over, | 77 | .port_handed_over = ehci_port_handed_over, |
78 | |||
79 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
78 | }; | 80 | }; |
79 | 81 | ||
80 | static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev) | 82 | static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev) |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3192f683f807..9a1384747f3b 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -93,6 +93,22 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) | |||
93 | qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); | 93 | qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); |
94 | qh->hw_alt_next = EHCI_LIST_END(ehci); | 94 | qh->hw_alt_next = EHCI_LIST_END(ehci); |
95 | 95 | ||
96 | /* Except for control endpoints, we make hardware maintain data | ||
97 | * toggle (like OHCI) ... here (re)initialize the toggle in the QH, | ||
98 | * and set the pseudo-toggle in udev. Only usb_clear_halt() will | ||
99 | * ever clear it. | ||
100 | */ | ||
101 | if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { | ||
102 | unsigned is_out, epnum; | ||
103 | |||
104 | is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8)); | ||
105 | epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f; | ||
106 | if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { | ||
107 | qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); | ||
108 | usb_settoggle (qh->dev, epnum, is_out, 1); | ||
109 | } | ||
110 | } | ||
111 | |||
96 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ | 112 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ |
97 | wmb (); | 113 | wmb (); |
98 | qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); | 114 | qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); |
@@ -123,6 +139,55 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
123 | 139 | ||
124 | /*-------------------------------------------------------------------------*/ | 140 | /*-------------------------------------------------------------------------*/ |
125 | 141 | ||
142 | static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh); | ||
143 | |||
144 | static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd, | ||
145 | struct usb_host_endpoint *ep) | ||
146 | { | ||
147 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
148 | struct ehci_qh *qh = ep->hcpriv; | ||
149 | unsigned long flags; | ||
150 | |||
151 | spin_lock_irqsave(&ehci->lock, flags); | ||
152 | qh->clearing_tt = 0; | ||
153 | if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) | ||
154 | && HC_IS_RUNNING(hcd->state)) | ||
155 | qh_link_async(ehci, qh); | ||
156 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
157 | } | ||
158 | |||
159 | static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh, | ||
160 | struct urb *urb, u32 token) | ||
161 | { | ||
162 | |||
163 | /* If an async split transaction gets an error or is unlinked, | ||
164 | * the TT buffer may be left in an indeterminate state. We | ||
165 | * have to clear the TT buffer. | ||
166 | * | ||
167 | * Note: this routine is never called for Isochronous transfers. | ||
168 | */ | ||
169 | if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { | ||
170 | #ifdef DEBUG | ||
171 | struct usb_device *tt = urb->dev->tt->hub; | ||
172 | dev_dbg(&tt->dev, | ||
173 | "clear tt buffer port %d, a%d ep%d t%08x\n", | ||
174 | urb->dev->ttport, urb->dev->devnum, | ||
175 | usb_pipeendpoint(urb->pipe), token); | ||
176 | #endif /* DEBUG */ | ||
177 | if (!ehci_is_TDI(ehci) | ||
178 | || urb->dev->tt->hub != | ||
179 | ehci_to_hcd(ehci)->self.root_hub) { | ||
180 | if (usb_hub_clear_tt_buffer(urb) == 0) | ||
181 | qh->clearing_tt = 1; | ||
182 | } else { | ||
183 | |||
184 | /* REVISIT ARC-derived cores don't clear the root | ||
185 | * hub TT buffer in this way... | ||
186 | */ | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | |||
126 | static int qtd_copy_status ( | 191 | static int qtd_copy_status ( |
127 | struct ehci_hcd *ehci, | 192 | struct ehci_hcd *ehci, |
128 | struct urb *urb, | 193 | struct urb *urb, |
@@ -149,6 +214,14 @@ static int qtd_copy_status ( | |||
149 | if (token & QTD_STS_BABBLE) { | 214 | if (token & QTD_STS_BABBLE) { |
150 | /* FIXME "must" disable babbling device's port too */ | 215 | /* FIXME "must" disable babbling device's port too */ |
151 | status = -EOVERFLOW; | 216 | status = -EOVERFLOW; |
217 | /* CERR nonzero + halt --> stall */ | ||
218 | } else if (QTD_CERR(token)) { | ||
219 | status = -EPIPE; | ||
220 | |||
221 | /* In theory, more than one of the following bits can be set | ||
222 | * since they are sticky and the transaction is retried. | ||
223 | * Which to test first is rather arbitrary. | ||
224 | */ | ||
152 | } else if (token & QTD_STS_MMF) { | 225 | } else if (token & QTD_STS_MMF) { |
153 | /* fs/ls interrupt xfer missed the complete-split */ | 226 | /* fs/ls interrupt xfer missed the complete-split */ |
154 | status = -EPROTO; | 227 | status = -EPROTO; |
@@ -157,21 +230,15 @@ static int qtd_copy_status ( | |||
157 | ? -ENOSR /* hc couldn't read data */ | 230 | ? -ENOSR /* hc couldn't read data */ |
158 | : -ECOMM; /* hc couldn't write data */ | 231 | : -ECOMM; /* hc couldn't write data */ |
159 | } else if (token & QTD_STS_XACT) { | 232 | } else if (token & QTD_STS_XACT) { |
160 | /* timeout, bad crc, wrong PID, etc; retried */ | 233 | /* timeout, bad CRC, wrong PID, etc */ |
161 | if (QTD_CERR (token)) | 234 | ehci_dbg(ehci, "devpath %s ep%d%s 3strikes\n", |
162 | status = -EPIPE; | 235 | urb->dev->devpath, |
163 | else { | 236 | usb_pipeendpoint(urb->pipe), |
164 | ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n", | 237 | usb_pipein(urb->pipe) ? "in" : "out"); |
165 | urb->dev->devpath, | 238 | status = -EPROTO; |
166 | usb_pipeendpoint (urb->pipe), | 239 | } else { /* unknown */ |
167 | usb_pipein (urb->pipe) ? "in" : "out"); | ||
168 | status = -EPROTO; | ||
169 | } | ||
170 | /* CERR nonzero + no errors + halt --> stall */ | ||
171 | } else if (QTD_CERR (token)) | ||
172 | status = -EPIPE; | ||
173 | else /* unknown */ | ||
174 | status = -EPROTO; | 240 | status = -EPROTO; |
241 | } | ||
175 | 242 | ||
176 | ehci_vdbg (ehci, | 243 | ehci_vdbg (ehci, |
177 | "dev%d ep%d%s qtd token %08x --> status %d\n", | 244 | "dev%d ep%d%s qtd token %08x --> status %d\n", |
@@ -179,28 +246,6 @@ static int qtd_copy_status ( | |||
179 | usb_pipeendpoint (urb->pipe), | 246 | usb_pipeendpoint (urb->pipe), |
180 | usb_pipein (urb->pipe) ? "in" : "out", | 247 | usb_pipein (urb->pipe) ? "in" : "out", |
181 | token, status); | 248 | token, status); |
182 | |||
183 | /* if async CSPLIT failed, try cleaning out the TT buffer */ | ||
184 | if (status != -EPIPE | ||
185 | && urb->dev->tt | ||
186 | && !usb_pipeint(urb->pipe) | ||
187 | && ((token & QTD_STS_MMF) != 0 | ||
188 | || QTD_CERR(token) == 0) | ||
189 | && (!ehci_is_TDI(ehci) | ||
190 | || urb->dev->tt->hub != | ||
191 | ehci_to_hcd(ehci)->self.root_hub)) { | ||
192 | #ifdef DEBUG | ||
193 | struct usb_device *tt = urb->dev->tt->hub; | ||
194 | dev_dbg (&tt->dev, | ||
195 | "clear tt buffer port %d, a%d ep%d t%08x\n", | ||
196 | urb->dev->ttport, urb->dev->devnum, | ||
197 | usb_pipeendpoint (urb->pipe), token); | ||
198 | #endif /* DEBUG */ | ||
199 | /* REVISIT ARC-derived cores don't clear the root | ||
200 | * hub TT buffer in this way... | ||
201 | */ | ||
202 | usb_hub_tt_clear_buffer (urb->dev, urb->pipe); | ||
203 | } | ||
204 | } | 249 | } |
205 | 250 | ||
206 | return status; | 251 | return status; |
@@ -391,9 +436,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
391 | /* qh unlinked; token in overlay may be most current */ | 436 | /* qh unlinked; token in overlay may be most current */ |
392 | if (state == QH_STATE_IDLE | 437 | if (state == QH_STATE_IDLE |
393 | && cpu_to_hc32(ehci, qtd->qtd_dma) | 438 | && cpu_to_hc32(ehci, qtd->qtd_dma) |
394 | == qh->hw_current) | 439 | == qh->hw_current) { |
395 | token = hc32_to_cpu(ehci, qh->hw_token); | 440 | token = hc32_to_cpu(ehci, qh->hw_token); |
396 | 441 | ||
442 | /* An unlink may leave an incomplete | ||
443 | * async transaction in the TT buffer. | ||
444 | * We have to clear it. | ||
445 | */ | ||
446 | ehci_clear_tt_buffer(ehci, qh, urb, token); | ||
447 | } | ||
448 | |||
397 | /* force halt for unlinked or blocked qh, so we'll | 449 | /* force halt for unlinked or blocked qh, so we'll |
398 | * patch the qh later and so that completions can't | 450 | * patch the qh later and so that completions can't |
399 | * activate it while we "know" it's stopped. | 451 | * activate it while we "know" it's stopped. |
@@ -419,6 +471,13 @@ halt: | |||
419 | && (qtd->hw_alt_next | 471 | && (qtd->hw_alt_next |
420 | & EHCI_LIST_END(ehci))) | 472 | & EHCI_LIST_END(ehci))) |
421 | last_status = -EINPROGRESS; | 473 | last_status = -EINPROGRESS; |
474 | |||
475 | /* As part of low/full-speed endpoint-halt processing | ||
476 | * we must clear the TT buffer (11.17.5). | ||
477 | */ | ||
478 | if (unlikely(last_status != -EINPROGRESS && | ||
479 | last_status != -EREMOTEIO)) | ||
480 | ehci_clear_tt_buffer(ehci, qh, urb, token); | ||
422 | } | 481 | } |
423 | 482 | ||
424 | /* if we're removing something not at the queue head, | 483 | /* if we're removing something not at the queue head, |
@@ -834,6 +893,7 @@ done: | |||
834 | qh->qh_state = QH_STATE_IDLE; | 893 | qh->qh_state = QH_STATE_IDLE; |
835 | qh->hw_info1 = cpu_to_hc32(ehci, info1); | 894 | qh->hw_info1 = cpu_to_hc32(ehci, info1); |
836 | qh->hw_info2 = cpu_to_hc32(ehci, info2); | 895 | qh->hw_info2 = cpu_to_hc32(ehci, info2); |
896 | usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); | ||
837 | qh_refresh (ehci, qh); | 897 | qh_refresh (ehci, qh); |
838 | return qh; | 898 | return qh; |
839 | } | 899 | } |
@@ -847,6 +907,10 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
847 | __hc32 dma = QH_NEXT(ehci, qh->qh_dma); | 907 | __hc32 dma = QH_NEXT(ehci, qh->qh_dma); |
848 | struct ehci_qh *head; | 908 | struct ehci_qh *head; |
849 | 909 | ||
910 | /* Don't link a QH if there's a Clear-TT-Buffer pending */ | ||
911 | if (unlikely(qh->clearing_tt)) | ||
912 | return; | ||
913 | |||
850 | /* (re)start the async schedule? */ | 914 | /* (re)start the async schedule? */ |
851 | head = ehci->async; | 915 | head = ehci->async; |
852 | timer_action_done (ehci, TIMER_ASYNC_OFF); | 916 | timer_action_done (ehci, TIMER_ASYNC_OFF); |
@@ -864,7 +928,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
864 | } | 928 | } |
865 | } | 929 | } |
866 | 930 | ||
867 | /* clear halt and maybe recover from silicon quirk */ | 931 | /* clear halt and/or toggle; and maybe recover from silicon quirk */ |
868 | if (qh->qh_state == QH_STATE_IDLE) | 932 | if (qh->qh_state == QH_STATE_IDLE) |
869 | qh_refresh (ehci, qh); | 933 | qh_refresh (ehci, qh); |
870 | 934 | ||
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 9d1babc7ff65..74f7f83b29ad 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -1619,11 +1619,14 @@ itd_complete ( | |||
1619 | desc->status = -EPROTO; | 1619 | desc->status = -EPROTO; |
1620 | 1620 | ||
1621 | /* HC need not update length with this error */ | 1621 | /* HC need not update length with this error */ |
1622 | if (!(t & EHCI_ISOC_BABBLE)) | 1622 | if (!(t & EHCI_ISOC_BABBLE)) { |
1623 | desc->actual_length = EHCI_ITD_LENGTH (t); | 1623 | desc->actual_length = EHCI_ITD_LENGTH(t); |
1624 | urb->actual_length += desc->actual_length; | ||
1625 | } | ||
1624 | } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { | 1626 | } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { |
1625 | desc->status = 0; | 1627 | desc->status = 0; |
1626 | desc->actual_length = EHCI_ITD_LENGTH (t); | 1628 | desc->actual_length = EHCI_ITD_LENGTH(t); |
1629 | urb->actual_length += desc->actual_length; | ||
1627 | } else { | 1630 | } else { |
1628 | /* URB was too late */ | 1631 | /* URB was too late */ |
1629 | desc->status = -EXDEV; | 1632 | desc->status = -EXDEV; |
@@ -2014,7 +2017,8 @@ sitd_complete ( | |||
2014 | desc->status = -EPROTO; | 2017 | desc->status = -EPROTO; |
2015 | } else { | 2018 | } else { |
2016 | desc->status = 0; | 2019 | desc->status = 0; |
2017 | desc->actual_length = desc->length - SITD_LENGTH (t); | 2020 | desc->actual_length = desc->length - SITD_LENGTH(t); |
2021 | urb->actual_length += desc->actual_length; | ||
2018 | } | 2022 | } |
2019 | stream->depth -= stream->interval << 3; | 2023 | stream->depth -= stream->interval << 3; |
2020 | 2024 | ||
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 90ad3395bb21..2bfff30f4704 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -354,7 +354,9 @@ struct ehci_qh { | |||
354 | unsigned short period; /* polling interval */ | 354 | unsigned short period; /* polling interval */ |
355 | unsigned short start; /* where polling starts */ | 355 | unsigned short start; /* where polling starts */ |
356 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ | 356 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ |
357 | |||
357 | struct usb_device *dev; /* access to TT */ | 358 | struct usb_device *dev; /* access to TT */ |
359 | unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ | ||
358 | } __attribute__ ((aligned (32))); | 360 | } __attribute__ ((aligned (32))); |
359 | 361 | ||
360 | /*-------------------------------------------------------------------------*/ | 362 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index bb63b68ddb77..62a226b61670 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c | |||
@@ -576,9 +576,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd) | |||
576 | out_be16(&usb->fhci->regs->usb_event, | 576 | out_be16(&usb->fhci->regs->usb_event, |
577 | usb->saved_msk); | 577 | usb->saved_msk); |
578 | } else if (usb->port_status == FHCI_PORT_DISABLED) { | 578 | } else if (usb->port_status == FHCI_PORT_DISABLED) { |
579 | if (fhci_ioports_check_bus_state(fhci) == 1 && | 579 | if (fhci_ioports_check_bus_state(fhci) == 1) |
580 | usb->port_status != FHCI_PORT_LOW && | ||
581 | usb->port_status != FHCI_PORT_FULL) | ||
582 | fhci_device_connected_interrupt(fhci); | 580 | fhci_device_connected_interrupt(fhci); |
583 | } | 581 | } |
584 | usb_er &= ~USB_E_RESET_MASK; | 582 | usb_er &= ~USB_E_RESET_MASK; |
@@ -605,9 +603,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd) | |||
605 | } | 603 | } |
606 | 604 | ||
607 | if (usb_er & USB_E_IDLE_MASK) { | 605 | if (usb_er & USB_E_IDLE_MASK) { |
608 | if (usb->port_status == FHCI_PORT_DISABLED && | 606 | if (usb->port_status == FHCI_PORT_DISABLED) { |
609 | usb->port_status != FHCI_PORT_LOW && | ||
610 | usb->port_status != FHCI_PORT_FULL) { | ||
611 | usb_er &= ~USB_E_RESET_MASK; | 607 | usb_er &= ~USB_E_RESET_MASK; |
612 | fhci_device_connected_interrupt(fhci); | 608 | fhci_device_connected_interrupt(fhci); |
613 | } else if (usb->port_status == | 609 | } else if (usb->port_status == |
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 3fa3a1702796..d4feebfc63bd 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
@@ -361,7 +361,7 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev) | |||
361 | 361 | ||
362 | static struct platform_driver isp1760_plat_driver = { | 362 | static struct platform_driver isp1760_plat_driver = { |
363 | .probe = isp1760_plat_probe, | 363 | .probe = isp1760_plat_probe, |
364 | .remove = isp1760_plat_remove, | 364 | .remove = __devexit_p(isp1760_plat_remove), |
365 | .driver = { | 365 | .driver = { |
366 | .name = "isp1760", | 366 | .name = "isp1760", |
367 | }, | 367 | }, |
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 180d7daa4099..e16ff605c458 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c | |||
@@ -35,13 +35,14 @@ | |||
35 | #include <mach/hardware.h> | 35 | #include <mach/hardware.h> |
36 | #include <mach/memory.h> | 36 | #include <mach/memory.h> |
37 | #include <mach/gpio.h> | 37 | #include <mach/gpio.h> |
38 | #include <mach/cputype.h> | ||
38 | 39 | ||
39 | #include <asm/mach-types.h> | 40 | #include <asm/mach-types.h> |
40 | 41 | ||
41 | #include "musb_core.h" | 42 | #include "musb_core.h" |
42 | 43 | ||
43 | #ifdef CONFIG_MACH_DAVINCI_EVM | 44 | #ifdef CONFIG_MACH_DAVINCI_EVM |
44 | #define GPIO_nVBUS_DRV 87 | 45 | #define GPIO_nVBUS_DRV 144 |
45 | #endif | 46 | #endif |
46 | 47 | ||
47 | #include "davinci.h" | 48 | #include "davinci.h" |
@@ -329,7 +330,6 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
329 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); | 330 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); |
330 | WARNING("VBUS error workaround (delay coming)\n"); | 331 | WARNING("VBUS error workaround (delay coming)\n"); |
331 | } else if (is_host_enabled(musb) && drvvbus) { | 332 | } else if (is_host_enabled(musb) && drvvbus) { |
332 | musb->is_active = 1; | ||
333 | MUSB_HST_MODE(musb); | 333 | MUSB_HST_MODE(musb); |
334 | musb->xceiv->default_a = 1; | 334 | musb->xceiv->default_a = 1; |
335 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | 335 | musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; |
@@ -343,7 +343,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
343 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); | 343 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); |
344 | } | 344 | } |
345 | 345 | ||
346 | /* NOTE: this must complete poweron within 100 msec */ | 346 | /* NOTE: this must complete poweron within 100 msec |
347 | * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. | ||
348 | */ | ||
347 | davinci_source_power(musb, drvvbus, 0); | 349 | davinci_source_power(musb, drvvbus, 0); |
348 | DBG(2, "VBUS %s (%s)%s, devctl %02x\n", | 350 | DBG(2, "VBUS %s (%s)%s, devctl %02x\n", |
349 | drvvbus ? "on" : "off", | 351 | drvvbus ? "on" : "off", |
@@ -411,6 +413,21 @@ int __init musb_platform_init(struct musb *musb) | |||
411 | __raw_writel(phy_ctrl, USB_PHY_CTRL); | 413 | __raw_writel(phy_ctrl, USB_PHY_CTRL); |
412 | } | 414 | } |
413 | 415 | ||
416 | /* On dm355, the default-A state machine needs DRVVBUS control. | ||
417 | * If we won't be a host, there's no need to turn it on. | ||
418 | */ | ||
419 | if (cpu_is_davinci_dm355()) { | ||
420 | u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); | ||
421 | |||
422 | if (is_host_enabled(musb)) { | ||
423 | deepsleep &= ~DRVVBUS_OVERRIDE; | ||
424 | } else { | ||
425 | deepsleep &= ~DRVVBUS_FORCE; | ||
426 | deepsleep |= DRVVBUS_OVERRIDE; | ||
427 | } | ||
428 | __raw_writel(deepsleep, DM355_DEEPSLEEP); | ||
429 | } | ||
430 | |||
414 | /* reset the controller */ | 431 | /* reset the controller */ |
415 | musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); | 432 | musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); |
416 | 433 | ||
@@ -437,6 +454,15 @@ int musb_platform_exit(struct musb *musb) | |||
437 | if (is_host_enabled(musb)) | 454 | if (is_host_enabled(musb)) |
438 | del_timer_sync(&otg_workaround); | 455 | del_timer_sync(&otg_workaround); |
439 | 456 | ||
457 | /* force VBUS off */ | ||
458 | if (cpu_is_davinci_dm355()) { | ||
459 | u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); | ||
460 | |||
461 | deepsleep &= ~DRVVBUS_FORCE; | ||
462 | deepsleep |= DRVVBUS_OVERRIDE; | ||
463 | __raw_writel(deepsleep, DM355_DEEPSLEEP); | ||
464 | } | ||
465 | |||
440 | davinci_source_power(musb, 0 /*off*/, 1); | 466 | davinci_source_power(musb, 0 /*off*/, 1); |
441 | 467 | ||
442 | /* delay, to avoid problems with module reload */ | 468 | /* delay, to avoid problems with module reload */ |
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 94a2a350a414..cf94511485f2 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
@@ -373,7 +373,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb, | |||
373 | musb_save_toggle(qh, is_in, urb); | 373 | musb_save_toggle(qh, is_in, urb); |
374 | break; | 374 | break; |
375 | case USB_ENDPOINT_XFER_ISOC: | 375 | case USB_ENDPOINT_XFER_ISOC: |
376 | if (urb->error_count) | 376 | if (status == 0 && urb->error_count) |
377 | status = -EXDEV; | 377 | status = -EXDEV; |
378 | break; | 378 | break; |
379 | } | 379 | } |
@@ -2235,13 +2235,30 @@ static void musb_h_stop(struct usb_hcd *hcd) | |||
2235 | static int musb_bus_suspend(struct usb_hcd *hcd) | 2235 | static int musb_bus_suspend(struct usb_hcd *hcd) |
2236 | { | 2236 | { |
2237 | struct musb *musb = hcd_to_musb(hcd); | 2237 | struct musb *musb = hcd_to_musb(hcd); |
2238 | u8 devctl; | ||
2238 | 2239 | ||
2239 | if (musb->xceiv->state == OTG_STATE_A_SUSPEND) | 2240 | if (!is_host_active(musb)) |
2240 | return 0; | 2241 | return 0; |
2241 | 2242 | ||
2242 | if (is_host_active(musb) && musb->is_active) { | 2243 | switch (musb->xceiv->state) { |
2243 | WARNING("trying to suspend as %s is_active=%i\n", | 2244 | case OTG_STATE_A_SUSPEND: |
2244 | otg_state_string(musb), musb->is_active); | 2245 | return 0; |
2246 | case OTG_STATE_A_WAIT_VRISE: | ||
2247 | /* ID could be grounded even if there's no device | ||
2248 | * on the other end of the cable. NOTE that the | ||
2249 | * A_WAIT_VRISE timers are messy with MUSB... | ||
2250 | */ | ||
2251 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
2252 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) | ||
2253 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | ||
2254 | break; | ||
2255 | default: | ||
2256 | break; | ||
2257 | } | ||
2258 | |||
2259 | if (musb->is_active) { | ||
2260 | WARNING("trying to suspend as %s while active\n", | ||
2261 | otg_state_string(musb)); | ||
2245 | return -EBUSY; | 2262 | return -EBUSY; |
2246 | } else | 2263 | } else |
2247 | return 0; | 2264 | return 0; |
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 69feeec1628c..aa884d072f0b 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -59,18 +59,4 @@ config NOP_USB_XCEIV | |||
59 | built-in with usb ip or which are autonomous and doesn't require any | 59 | built-in with usb ip or which are autonomous and doesn't require any |
60 | phy programming such as ISP1x04 etc. | 60 | phy programming such as ISP1x04 etc. |
61 | 61 | ||
62 | config USB_LANGWELL_OTG | ||
63 | tristate "Intel Langwell USB OTG dual-role support" | ||
64 | depends on USB && MRST | ||
65 | select USB_OTG | ||
66 | select USB_OTG_UTILS | ||
67 | help | ||
68 | Say Y here if you want to build Intel Langwell USB OTG | ||
69 | transciever driver in kernel. This driver implements role | ||
70 | switch between EHCI host driver and Langwell USB OTG | ||
71 | client driver. | ||
72 | |||
73 | To compile this driver as a module, choose M here: the | ||
74 | module will be called langwell_otg. | ||
75 | |||
76 | endif # USB || OTG | 62 | endif # USB || OTG |
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 6d1abdd3c0ac..208167856529 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile | |||
@@ -9,7 +9,6 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o | |||
9 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o | 9 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o |
10 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o | 10 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o |
11 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o | 11 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o |
12 | obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o | ||
13 | obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o | 12 | obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o |
14 | 13 | ||
15 | ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG | 14 | ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG |
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c deleted file mode 100644 index 6f628d0e9f39..000000000000 --- a/drivers/usb/otg/langwell_otg.c +++ /dev/null | |||
@@ -1,1915 +0,0 @@ | |||
1 | /* | ||
2 | * Intel Langwell USB OTG transceiver driver | ||
3 | * Copyright (C) 2008 - 2009, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | * | ||
18 | */ | ||
19 | /* This driver helps to switch Langwell OTG controller function between host | ||
20 | * and peripheral. It works with EHCI driver and Langwell client controller | ||
21 | * driver together. | ||
22 | */ | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/pci.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/moduleparam.h> | ||
31 | #include <linux/usb/ch9.h> | ||
32 | #include <linux/usb/gadget.h> | ||
33 | #include <linux/usb.h> | ||
34 | #include <linux/usb/otg.h> | ||
35 | #include <linux/notifier.h> | ||
36 | #include <asm/ipc_defs.h> | ||
37 | #include <linux/delay.h> | ||
38 | #include "../core/hcd.h" | ||
39 | |||
40 | #include <linux/usb/langwell_otg.h> | ||
41 | |||
42 | #define DRIVER_DESC "Intel Langwell USB OTG transceiver driver" | ||
43 | #define DRIVER_VERSION "3.0.0.32L.0002" | ||
44 | |||
45 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
46 | MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>"); | ||
47 | MODULE_VERSION(DRIVER_VERSION); | ||
48 | MODULE_LICENSE("GPL"); | ||
49 | |||
50 | static const char driver_name[] = "langwell_otg"; | ||
51 | |||
52 | static int langwell_otg_probe(struct pci_dev *pdev, | ||
53 | const struct pci_device_id *id); | ||
54 | static void langwell_otg_remove(struct pci_dev *pdev); | ||
55 | static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message); | ||
56 | static int langwell_otg_resume(struct pci_dev *pdev); | ||
57 | |||
58 | static int langwell_otg_set_host(struct otg_transceiver *otg, | ||
59 | struct usb_bus *host); | ||
60 | static int langwell_otg_set_peripheral(struct otg_transceiver *otg, | ||
61 | struct usb_gadget *gadget); | ||
62 | static int langwell_otg_start_srp(struct otg_transceiver *otg); | ||
63 | |||
64 | static const struct pci_device_id pci_ids[] = {{ | ||
65 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), | ||
66 | .class_mask = ~0, | ||
67 | .vendor = 0x8086, | ||
68 | .device = 0x0811, | ||
69 | .subvendor = PCI_ANY_ID, | ||
70 | .subdevice = PCI_ANY_ID, | ||
71 | }, { /* end: all zeroes */ } | ||
72 | }; | ||
73 | |||
74 | static struct pci_driver otg_pci_driver = { | ||
75 | .name = (char *) driver_name, | ||
76 | .id_table = pci_ids, | ||
77 | |||
78 | .probe = langwell_otg_probe, | ||
79 | .remove = langwell_otg_remove, | ||
80 | |||
81 | .suspend = langwell_otg_suspend, | ||
82 | .resume = langwell_otg_resume, | ||
83 | }; | ||
84 | |||
85 | static const char *state_string(enum usb_otg_state state) | ||
86 | { | ||
87 | switch (state) { | ||
88 | case OTG_STATE_A_IDLE: | ||
89 | return "a_idle"; | ||
90 | case OTG_STATE_A_WAIT_VRISE: | ||
91 | return "a_wait_vrise"; | ||
92 | case OTG_STATE_A_WAIT_BCON: | ||
93 | return "a_wait_bcon"; | ||
94 | case OTG_STATE_A_HOST: | ||
95 | return "a_host"; | ||
96 | case OTG_STATE_A_SUSPEND: | ||
97 | return "a_suspend"; | ||
98 | case OTG_STATE_A_PERIPHERAL: | ||
99 | return "a_peripheral"; | ||
100 | case OTG_STATE_A_WAIT_VFALL: | ||
101 | return "a_wait_vfall"; | ||
102 | case OTG_STATE_A_VBUS_ERR: | ||
103 | return "a_vbus_err"; | ||
104 | case OTG_STATE_B_IDLE: | ||
105 | return "b_idle"; | ||
106 | case OTG_STATE_B_SRP_INIT: | ||
107 | return "b_srp_init"; | ||
108 | case OTG_STATE_B_PERIPHERAL: | ||
109 | return "b_peripheral"; | ||
110 | case OTG_STATE_B_WAIT_ACON: | ||
111 | return "b_wait_acon"; | ||
112 | case OTG_STATE_B_HOST: | ||
113 | return "b_host"; | ||
114 | default: | ||
115 | return "UNDEFINED"; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /* HSM timers */ | ||
120 | static inline struct langwell_otg_timer *otg_timer_initializer | ||
121 | (void (*function)(unsigned long), unsigned long expires, unsigned long data) | ||
122 | { | ||
123 | struct langwell_otg_timer *timer; | ||
124 | timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL); | ||
125 | timer->function = function; | ||
126 | timer->expires = expires; | ||
127 | timer->data = data; | ||
128 | return timer; | ||
129 | } | ||
130 | |||
131 | static struct langwell_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, | ||
132 | *a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_res_tmr, | ||
133 | *b_bus_suspend_tmr; | ||
134 | |||
135 | static struct list_head active_timers; | ||
136 | |||
137 | static struct langwell_otg *the_transceiver; | ||
138 | |||
139 | /* host/client notify transceiver when event affects HNP state */ | ||
140 | void langwell_update_transceiver() | ||
141 | { | ||
142 | otg_dbg("transceiver driver is notified\n"); | ||
143 | queue_work(the_transceiver->qwork, &the_transceiver->work); | ||
144 | } | ||
145 | EXPORT_SYMBOL(langwell_update_transceiver); | ||
146 | |||
147 | static int langwell_otg_set_host(struct otg_transceiver *otg, | ||
148 | struct usb_bus *host) | ||
149 | { | ||
150 | otg->host = host; | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int langwell_otg_set_peripheral(struct otg_transceiver *otg, | ||
156 | struct usb_gadget *gadget) | ||
157 | { | ||
158 | otg->gadget = gadget; | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static int langwell_otg_set_power(struct otg_transceiver *otg, | ||
164 | unsigned mA) | ||
165 | { | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | /* A-device drives vbus, controlled through PMIC CHRGCNTL register*/ | ||
170 | static void langwell_otg_drv_vbus(int on) | ||
171 | { | ||
172 | struct ipc_pmic_reg_data pmic_data = {0}; | ||
173 | struct ipc_pmic_reg_data battery_data; | ||
174 | |||
175 | /* Check if battery is attached or not */ | ||
176 | battery_data.pmic_reg_data[0].register_address = 0xd2; | ||
177 | battery_data.ioc = 0; | ||
178 | battery_data.num_entries = 1; | ||
179 | if (ipc_pmic_register_read(&battery_data)) { | ||
180 | otg_dbg("Failed to read PMIC register 0xd2.\n"); | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | if ((battery_data.pmic_reg_data[0].value & 0x20) == 0) { | ||
185 | otg_dbg("no battery attached\n"); | ||
186 | return; | ||
187 | } | ||
188 | |||
189 | /* Workaround for battery attachment issue */ | ||
190 | if (battery_data.pmic_reg_data[0].value == 0x34) { | ||
191 | otg_dbg("battery \n"); | ||
192 | return; | ||
193 | } | ||
194 | |||
195 | otg_dbg("battery attached\n"); | ||
196 | |||
197 | pmic_data.ioc = 0; | ||
198 | pmic_data.pmic_reg_data[0].register_address = 0xD4; | ||
199 | pmic_data.num_entries = 1; | ||
200 | if (on) | ||
201 | pmic_data.pmic_reg_data[0].value = 0x20; | ||
202 | else | ||
203 | pmic_data.pmic_reg_data[0].value = 0xc0; | ||
204 | |||
205 | if (ipc_pmic_register_write(&pmic_data, TRUE)) | ||
206 | otg_dbg("Failed to write PMIC.\n"); | ||
207 | |||
208 | } | ||
209 | |||
210 | /* charge vbus or discharge vbus through a resistor to ground */ | ||
211 | static void langwell_otg_chrg_vbus(int on) | ||
212 | { | ||
213 | |||
214 | u32 val; | ||
215 | |||
216 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
217 | |||
218 | if (on) | ||
219 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC, | ||
220 | the_transceiver->regs + CI_OTGSC); | ||
221 | else | ||
222 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD, | ||
223 | the_transceiver->regs + CI_OTGSC); | ||
224 | |||
225 | } | ||
226 | |||
227 | /* Start SRP */ | ||
228 | static int langwell_otg_start_srp(struct otg_transceiver *otg) | ||
229 | { | ||
230 | u32 val; | ||
231 | |||
232 | otg_dbg("Start SRP ->\n"); | ||
233 | |||
234 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
235 | |||
236 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, | ||
237 | the_transceiver->regs + CI_OTGSC); | ||
238 | |||
239 | /* Check if the data plus is finished or not */ | ||
240 | msleep(8); | ||
241 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
242 | if (val & (OTGSC_HADP | OTGSC_DP)) | ||
243 | otg_dbg("DataLine SRP Error\n"); | ||
244 | |||
245 | /* FIXME: VBus SRP */ | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | |||
251 | /* stop SOF via bus_suspend */ | ||
252 | static void langwell_otg_loc_sof(int on) | ||
253 | { | ||
254 | struct usb_hcd *hcd; | ||
255 | int err; | ||
256 | |||
257 | otg_dbg("loc_sof -> %d\n", on); | ||
258 | |||
259 | hcd = bus_to_hcd(the_transceiver->otg.host); | ||
260 | if (on) | ||
261 | err = hcd->driver->bus_resume(hcd); | ||
262 | else | ||
263 | err = hcd->driver->bus_suspend(hcd); | ||
264 | |||
265 | if (err) | ||
266 | otg_dbg("Failed to resume/suspend bus - %d\n", err); | ||
267 | } | ||
268 | |||
269 | static void langwell_otg_phy_low_power(int on) | ||
270 | { | ||
271 | u32 val; | ||
272 | |||
273 | otg_dbg("phy low power mode-> %d\n", on); | ||
274 | |||
275 | val = readl(the_transceiver->regs + CI_HOSTPC1); | ||
276 | if (on) | ||
277 | writel(val | HOSTPC1_PHCD, the_transceiver->regs + CI_HOSTPC1); | ||
278 | else | ||
279 | writel(val & ~HOSTPC1_PHCD, the_transceiver->regs + CI_HOSTPC1); | ||
280 | } | ||
281 | |||
282 | /* Enable/Disable OTG interrupt */ | ||
283 | static void langwell_otg_intr(int on) | ||
284 | { | ||
285 | u32 val; | ||
286 | |||
287 | otg_dbg("interrupt -> %d\n", on); | ||
288 | |||
289 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
290 | if (on) { | ||
291 | val = val | (OTGSC_INTEN_MASK | OTGSC_IDPU); | ||
292 | writel(val, the_transceiver->regs + CI_OTGSC); | ||
293 | } else { | ||
294 | val = val & ~(OTGSC_INTEN_MASK | OTGSC_IDPU); | ||
295 | writel(val, the_transceiver->regs + CI_OTGSC); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | /* set HAAR: Hardware Assist Auto-Reset */ | ||
300 | static void langwell_otg_HAAR(int on) | ||
301 | { | ||
302 | u32 val; | ||
303 | |||
304 | otg_dbg("HAAR -> %d\n", on); | ||
305 | |||
306 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
307 | if (on) | ||
308 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR, | ||
309 | the_transceiver->regs + CI_OTGSC); | ||
310 | else | ||
311 | writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR, | ||
312 | the_transceiver->regs + CI_OTGSC); | ||
313 | } | ||
314 | |||
315 | /* set HABA: Hardware Assist B-Disconnect to A-Connect */ | ||
316 | static void langwell_otg_HABA(int on) | ||
317 | { | ||
318 | u32 val; | ||
319 | |||
320 | otg_dbg("HABA -> %d\n", on); | ||
321 | |||
322 | val = readl(the_transceiver->regs + CI_OTGSC); | ||
323 | if (on) | ||
324 | writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA, | ||
325 | the_transceiver->regs + CI_OTGSC); | ||
326 | else | ||
327 | writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA, | ||
328 | the_transceiver->regs + CI_OTGSC); | ||
329 | } | ||
330 | |||
331 | static int langwell_otg_check_se0_srp(int on) | ||
332 | { | ||
333 | u32 val; | ||
334 | |||
335 | int delay_time = TB_SE0_SRP * 10; /* step is 100us */ | ||
336 | |||
337 | otg_dbg("check_se0_srp -> \n"); | ||
338 | |||
339 | do { | ||
340 | udelay(100); | ||
341 | if (!delay_time--) | ||
342 | break; | ||
343 | val = readl(the_transceiver->regs + CI_PORTSC1); | ||
344 | val &= PORTSC_LS; | ||
345 | } while (!val); | ||
346 | |||
347 | otg_dbg("check_se0_srp <- \n"); | ||
348 | return val; | ||
349 | } | ||
350 | |||
351 | /* The timeout callback function to set time out bit */ | ||
352 | static void set_tmout(unsigned long indicator) | ||
353 | { | ||
354 | *(int *)indicator = 1; | ||
355 | } | ||
356 | |||
357 | void langwell_otg_nsf_msg(unsigned long indicator) | ||
358 | { | ||
359 | switch (indicator) { | ||
360 | case 2: | ||
361 | case 4: | ||
362 | case 6: | ||
363 | case 7: | ||
364 | printk(KERN_ERR "OTG:NSF-%lu - deivce not responding\n", | ||
365 | indicator); | ||
366 | break; | ||
367 | case 3: | ||
368 | printk(KERN_ERR "OTG:NSF-%lu - deivce not supported\n", | ||
369 | indicator); | ||
370 | break; | ||
371 | default: | ||
372 | printk(KERN_ERR "Do not have this kind of NSF\n"); | ||
373 | break; | ||
374 | } | ||
375 | } | ||
376 | |||
377 | /* Initialize timers */ | ||
378 | static void langwell_otg_init_timers(struct otg_hsm *hsm) | ||
379 | { | ||
380 | /* HSM used timers */ | ||
381 | a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, | ||
382 | (unsigned long)&hsm->a_wait_vrise_tmout); | ||
383 | a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON, | ||
384 | (unsigned long)&hsm->a_wait_bcon_tmout); | ||
385 | a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, | ||
386 | (unsigned long)&hsm->a_aidl_bdis_tmout); | ||
387 | b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST, | ||
388 | (unsigned long)&hsm->b_ase0_brst_tmout); | ||
389 | b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, | ||
390 | (unsigned long)&hsm->b_se0_srp); | ||
391 | b_srp_res_tmr = otg_timer_initializer(&set_tmout, TB_SRP_RES, | ||
392 | (unsigned long)&hsm->b_srp_res_tmout); | ||
393 | b_bus_suspend_tmr = otg_timer_initializer(&set_tmout, TB_BUS_SUSPEND, | ||
394 | (unsigned long)&hsm->b_bus_suspend_tmout); | ||
395 | } | ||
396 | |||
397 | /* Free timers */ | ||
398 | static void langwell_otg_free_timers(void) | ||
399 | { | ||
400 | kfree(a_wait_vrise_tmr); | ||
401 | kfree(a_wait_bcon_tmr); | ||
402 | kfree(a_aidl_bdis_tmr); | ||
403 | kfree(b_ase0_brst_tmr); | ||
404 | kfree(b_se0_srp_tmr); | ||
405 | kfree(b_srp_res_tmr); | ||
406 | kfree(b_bus_suspend_tmr); | ||
407 | } | ||
408 | |||
409 | /* Add timer to timer list */ | ||
410 | static void langwell_otg_add_timer(void *gtimer) | ||
411 | { | ||
412 | struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; | ||
413 | struct langwell_otg_timer *tmp_timer; | ||
414 | u32 val32; | ||
415 | |||
416 | /* Check if the timer is already in the active list, | ||
417 | * if so update timer count | ||
418 | */ | ||
419 | list_for_each_entry(tmp_timer, &active_timers, list) | ||
420 | if (tmp_timer == timer) { | ||
421 | timer->count = timer->expires; | ||
422 | return; | ||
423 | } | ||
424 | timer->count = timer->expires; | ||
425 | |||
426 | if (list_empty(&active_timers)) { | ||
427 | val32 = readl(the_transceiver->regs + CI_OTGSC); | ||
428 | writel(val32 | OTGSC_1MSE, the_transceiver->regs + CI_OTGSC); | ||
429 | } | ||
430 | |||
431 | list_add_tail(&timer->list, &active_timers); | ||
432 | } | ||
433 | |||
434 | /* Remove timer from the timer list; clear timeout status */ | ||
435 | static void langwell_otg_del_timer(void *gtimer) | ||
436 | { | ||
437 | struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; | ||
438 | struct langwell_otg_timer *tmp_timer, *del_tmp; | ||
439 | u32 val32; | ||
440 | |||
441 | list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) | ||
442 | if (tmp_timer == timer) | ||
443 | list_del(&timer->list); | ||
444 | |||
445 | if (list_empty(&active_timers)) { | ||
446 | val32 = readl(the_transceiver->regs + CI_OTGSC); | ||
447 | writel(val32 & ~OTGSC_1MSE, the_transceiver->regs + CI_OTGSC); | ||
448 | } | ||
449 | } | ||
450 | |||
451 | /* Reduce timer count by 1, and find timeout conditions.*/ | ||
452 | static int langwell_otg_tick_timer(u32 *int_sts) | ||
453 | { | ||
454 | struct langwell_otg_timer *tmp_timer, *del_tmp; | ||
455 | int expired = 0; | ||
456 | |||
457 | list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { | ||
458 | tmp_timer->count--; | ||
459 | /* check if timer expires */ | ||
460 | if (!tmp_timer->count) { | ||
461 | list_del(&tmp_timer->list); | ||
462 | tmp_timer->function(tmp_timer->data); | ||
463 | expired = 1; | ||
464 | } | ||
465 | } | ||
466 | |||
467 | if (list_empty(&active_timers)) { | ||
468 | otg_dbg("tick timer: disable 1ms int\n"); | ||
469 | *int_sts = *int_sts & ~OTGSC_1MSE; | ||
470 | } | ||
471 | return expired; | ||
472 | } | ||
473 | |||
474 | static void reset_otg(void) | ||
475 | { | ||
476 | u32 val; | ||
477 | int delay_time = 1000; | ||
478 | |||
479 | otg_dbg("reseting OTG controller ...\n"); | ||
480 | val = readl(the_transceiver->regs + CI_USBCMD); | ||
481 | writel(val | USBCMD_RST, the_transceiver->regs + CI_USBCMD); | ||
482 | do { | ||
483 | udelay(100); | ||
484 | if (!delay_time--) | ||
485 | otg_dbg("reset timeout\n"); | ||
486 | val = readl(the_transceiver->regs + CI_USBCMD); | ||
487 | val &= USBCMD_RST; | ||
488 | } while (val != 0); | ||
489 | otg_dbg("reset done.\n"); | ||
490 | } | ||
491 | |||
492 | static void set_host_mode(void) | ||
493 | { | ||
494 | u32 val; | ||
495 | |||
496 | reset_otg(); | ||
497 | val = readl(the_transceiver->regs + CI_USBMODE); | ||
498 | val = (val & (~USBMODE_CM)) | USBMODE_HOST; | ||
499 | writel(val, the_transceiver->regs + CI_USBMODE); | ||
500 | } | ||
501 | |||
502 | static void set_client_mode(void) | ||
503 | { | ||
504 | u32 val; | ||
505 | |||
506 | reset_otg(); | ||
507 | val = readl(the_transceiver->regs + CI_USBMODE); | ||
508 | val = (val & (~USBMODE_CM)) | USBMODE_DEVICE; | ||
509 | writel(val, the_transceiver->regs + CI_USBMODE); | ||
510 | } | ||
511 | |||
512 | static void init_hsm(void) | ||
513 | { | ||
514 | struct langwell_otg *langwell = the_transceiver; | ||
515 | u32 val32; | ||
516 | |||
517 | /* read OTGSC after reset */ | ||
518 | val32 = readl(langwell->regs + CI_OTGSC); | ||
519 | otg_dbg("%s: OTGSC init value = 0x%x\n", __func__, val32); | ||
520 | |||
521 | /* set init state */ | ||
522 | if (val32 & OTGSC_ID) { | ||
523 | langwell->hsm.id = 1; | ||
524 | langwell->otg.default_a = 0; | ||
525 | set_client_mode(); | ||
526 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
527 | langwell_otg_drv_vbus(0); | ||
528 | } else { | ||
529 | langwell->hsm.id = 0; | ||
530 | langwell->otg.default_a = 1; | ||
531 | set_host_mode(); | ||
532 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
533 | } | ||
534 | |||
535 | /* set session indicator */ | ||
536 | if (val32 & OTGSC_BSE) | ||
537 | langwell->hsm.b_sess_end = 1; | ||
538 | if (val32 & OTGSC_BSV) | ||
539 | langwell->hsm.b_sess_vld = 1; | ||
540 | if (val32 & OTGSC_ASV) | ||
541 | langwell->hsm.a_sess_vld = 1; | ||
542 | if (val32 & OTGSC_AVV) | ||
543 | langwell->hsm.a_vbus_vld = 1; | ||
544 | |||
545 | /* defautly power the bus */ | ||
546 | langwell->hsm.a_bus_req = 1; | ||
547 | langwell->hsm.a_bus_drop = 0; | ||
548 | /* defautly don't request bus as B device */ | ||
549 | langwell->hsm.b_bus_req = 0; | ||
550 | /* no system error */ | ||
551 | langwell->hsm.a_clr_err = 0; | ||
552 | } | ||
553 | |||
554 | static irqreturn_t otg_dummy_irq(int irq, void *_dev) | ||
555 | { | ||
556 | void __iomem *reg_base = _dev; | ||
557 | u32 val; | ||
558 | u32 int_mask = 0; | ||
559 | |||
560 | val = readl(reg_base + CI_USBMODE); | ||
561 | if ((val & USBMODE_CM) != USBMODE_DEVICE) | ||
562 | return IRQ_NONE; | ||
563 | |||
564 | val = readl(reg_base + CI_USBSTS); | ||
565 | int_mask = val & INTR_DUMMY_MASK; | ||
566 | |||
567 | if (int_mask == 0) | ||
568 | return IRQ_NONE; | ||
569 | |||
570 | /* clear hsm.b_conn here since host driver can't detect it | ||
571 | * otg_dummy_irq called means B-disconnect happened. | ||
572 | */ | ||
573 | if (the_transceiver->hsm.b_conn) { | ||
574 | the_transceiver->hsm.b_conn = 0; | ||
575 | if (spin_trylock(&the_transceiver->wq_lock)) { | ||
576 | queue_work(the_transceiver->qwork, | ||
577 | &the_transceiver->work); | ||
578 | spin_unlock(&the_transceiver->wq_lock); | ||
579 | } | ||
580 | } | ||
581 | /* Clear interrupts */ | ||
582 | writel(int_mask, reg_base + CI_USBSTS); | ||
583 | return IRQ_HANDLED; | ||
584 | } | ||
585 | |||
586 | static irqreturn_t otg_irq(int irq, void *_dev) | ||
587 | { | ||
588 | struct langwell_otg *langwell = _dev; | ||
589 | u32 int_sts, int_en; | ||
590 | u32 int_mask = 0; | ||
591 | int flag = 0; | ||
592 | |||
593 | int_sts = readl(langwell->regs + CI_OTGSC); | ||
594 | int_en = (int_sts & OTGSC_INTEN_MASK) >> 8; | ||
595 | int_mask = int_sts & int_en; | ||
596 | if (int_mask == 0) | ||
597 | return IRQ_NONE; | ||
598 | |||
599 | if (int_mask & OTGSC_IDIS) { | ||
600 | otg_dbg("%s: id change int\n", __func__); | ||
601 | langwell->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; | ||
602 | flag = 1; | ||
603 | } | ||
604 | if (int_mask & OTGSC_DPIS) { | ||
605 | otg_dbg("%s: data pulse int\n", __func__); | ||
606 | langwell->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; | ||
607 | flag = 1; | ||
608 | } | ||
609 | if (int_mask & OTGSC_BSEIS) { | ||
610 | otg_dbg("%s: b session end int\n", __func__); | ||
611 | langwell->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; | ||
612 | flag = 1; | ||
613 | } | ||
614 | if (int_mask & OTGSC_BSVIS) { | ||
615 | otg_dbg("%s: b session valid int\n", __func__); | ||
616 | langwell->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; | ||
617 | flag = 1; | ||
618 | } | ||
619 | if (int_mask & OTGSC_ASVIS) { | ||
620 | otg_dbg("%s: a session valid int\n", __func__); | ||
621 | langwell->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; | ||
622 | flag = 1; | ||
623 | } | ||
624 | if (int_mask & OTGSC_AVVIS) { | ||
625 | otg_dbg("%s: a vbus valid int\n", __func__); | ||
626 | langwell->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; | ||
627 | flag = 1; | ||
628 | } | ||
629 | |||
630 | if (int_mask & OTGSC_1MSS) { | ||
631 | /* need to schedule otg_work if any timer is expired */ | ||
632 | if (langwell_otg_tick_timer(&int_sts)) | ||
633 | flag = 1; | ||
634 | } | ||
635 | |||
636 | writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, | ||
637 | langwell->regs + CI_OTGSC); | ||
638 | if (flag) | ||
639 | queue_work(langwell->qwork, &langwell->work); | ||
640 | |||
641 | return IRQ_HANDLED; | ||
642 | } | ||
643 | |||
644 | static void langwell_otg_work(struct work_struct *work) | ||
645 | { | ||
646 | struct langwell_otg *langwell = container_of(work, | ||
647 | struct langwell_otg, work); | ||
648 | int retval; | ||
649 | |||
650 | otg_dbg("%s: old state = %s\n", __func__, | ||
651 | state_string(langwell->otg.state)); | ||
652 | |||
653 | switch (langwell->otg.state) { | ||
654 | case OTG_STATE_UNDEFINED: | ||
655 | case OTG_STATE_B_IDLE: | ||
656 | if (!langwell->hsm.id) { | ||
657 | langwell_otg_del_timer(b_srp_res_tmr); | ||
658 | langwell->otg.default_a = 1; | ||
659 | langwell->hsm.a_srp_det = 0; | ||
660 | |||
661 | langwell_otg_chrg_vbus(0); | ||
662 | langwell_otg_drv_vbus(0); | ||
663 | |||
664 | set_host_mode(); | ||
665 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
666 | queue_work(langwell->qwork, &langwell->work); | ||
667 | } else if (langwell->hsm.b_srp_res_tmout) { | ||
668 | langwell->hsm.b_srp_res_tmout = 0; | ||
669 | langwell->hsm.b_bus_req = 0; | ||
670 | langwell_otg_nsf_msg(6); | ||
671 | } else if (langwell->hsm.b_sess_vld) { | ||
672 | langwell_otg_del_timer(b_srp_res_tmr); | ||
673 | langwell->hsm.b_sess_end = 0; | ||
674 | langwell->hsm.a_bus_suspend = 0; | ||
675 | |||
676 | langwell_otg_chrg_vbus(0); | ||
677 | if (langwell->client_ops) { | ||
678 | langwell->client_ops->resume(langwell->pdev); | ||
679 | langwell->otg.state = OTG_STATE_B_PERIPHERAL; | ||
680 | } else | ||
681 | otg_dbg("client driver not loaded.\n"); | ||
682 | |||
683 | } else if (langwell->hsm.b_bus_req && | ||
684 | (langwell->hsm.b_sess_end)) { | ||
685 | /* workaround for b_se0_srp detection */ | ||
686 | retval = langwell_otg_check_se0_srp(0); | ||
687 | if (retval) { | ||
688 | langwell->hsm.b_bus_req = 0; | ||
689 | otg_dbg("LS is not SE0, try again later\n"); | ||
690 | } else { | ||
691 | /* Start SRP */ | ||
692 | langwell_otg_start_srp(&langwell->otg); | ||
693 | langwell_otg_add_timer(b_srp_res_tmr); | ||
694 | } | ||
695 | } | ||
696 | break; | ||
697 | case OTG_STATE_B_SRP_INIT: | ||
698 | if (!langwell->hsm.id) { | ||
699 | langwell->otg.default_a = 1; | ||
700 | langwell->hsm.a_srp_det = 0; | ||
701 | |||
702 | langwell_otg_drv_vbus(0); | ||
703 | langwell_otg_chrg_vbus(0); | ||
704 | |||
705 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
706 | queue_work(langwell->qwork, &langwell->work); | ||
707 | } else if (langwell->hsm.b_sess_vld) { | ||
708 | langwell_otg_chrg_vbus(0); | ||
709 | if (langwell->client_ops) { | ||
710 | langwell->client_ops->resume(langwell->pdev); | ||
711 | langwell->otg.state = OTG_STATE_B_PERIPHERAL; | ||
712 | } else | ||
713 | otg_dbg("client driver not loaded.\n"); | ||
714 | } | ||
715 | break; | ||
716 | case OTG_STATE_B_PERIPHERAL: | ||
717 | if (!langwell->hsm.id) { | ||
718 | langwell->otg.default_a = 1; | ||
719 | langwell->hsm.a_srp_det = 0; | ||
720 | |||
721 | langwell_otg_drv_vbus(0); | ||
722 | langwell_otg_chrg_vbus(0); | ||
723 | set_host_mode(); | ||
724 | |||
725 | if (langwell->client_ops) { | ||
726 | langwell->client_ops->suspend(langwell->pdev, | ||
727 | PMSG_FREEZE); | ||
728 | } else | ||
729 | otg_dbg("client driver has been removed.\n"); | ||
730 | |||
731 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
732 | queue_work(langwell->qwork, &langwell->work); | ||
733 | } else if (!langwell->hsm.b_sess_vld) { | ||
734 | langwell->hsm.b_hnp_enable = 0; | ||
735 | |||
736 | if (langwell->client_ops) { | ||
737 | langwell->client_ops->suspend(langwell->pdev, | ||
738 | PMSG_FREEZE); | ||
739 | } else | ||
740 | otg_dbg("client driver has been removed.\n"); | ||
741 | |||
742 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
743 | } else if (langwell->hsm.b_bus_req && langwell->hsm.b_hnp_enable | ||
744 | && langwell->hsm.a_bus_suspend) { | ||
745 | |||
746 | if (langwell->client_ops) { | ||
747 | langwell->client_ops->suspend(langwell->pdev, | ||
748 | PMSG_FREEZE); | ||
749 | } else | ||
750 | otg_dbg("client driver has been removed.\n"); | ||
751 | |||
752 | langwell_otg_HAAR(1); | ||
753 | langwell->hsm.a_conn = 0; | ||
754 | |||
755 | if (langwell->host_ops) { | ||
756 | langwell->host_ops->probe(langwell->pdev, | ||
757 | langwell->host_ops->id_table); | ||
758 | langwell->otg.state = OTG_STATE_B_WAIT_ACON; | ||
759 | } else | ||
760 | otg_dbg("host driver not loaded.\n"); | ||
761 | |||
762 | langwell->hsm.a_bus_resume = 0; | ||
763 | langwell->hsm.b_ase0_brst_tmout = 0; | ||
764 | langwell_otg_add_timer(b_ase0_brst_tmr); | ||
765 | } | ||
766 | break; | ||
767 | |||
768 | case OTG_STATE_B_WAIT_ACON: | ||
769 | if (!langwell->hsm.id) { | ||
770 | langwell_otg_del_timer(b_ase0_brst_tmr); | ||
771 | langwell->otg.default_a = 1; | ||
772 | langwell->hsm.a_srp_det = 0; | ||
773 | |||
774 | langwell_otg_drv_vbus(0); | ||
775 | langwell_otg_chrg_vbus(0); | ||
776 | set_host_mode(); | ||
777 | |||
778 | langwell_otg_HAAR(0); | ||
779 | if (langwell->host_ops) | ||
780 | langwell->host_ops->remove(langwell->pdev); | ||
781 | else | ||
782 | otg_dbg("host driver has been removed.\n"); | ||
783 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
784 | queue_work(langwell->qwork, &langwell->work); | ||
785 | } else if (!langwell->hsm.b_sess_vld) { | ||
786 | langwell_otg_del_timer(b_ase0_brst_tmr); | ||
787 | langwell->hsm.b_hnp_enable = 0; | ||
788 | langwell->hsm.b_bus_req = 0; | ||
789 | langwell_otg_chrg_vbus(0); | ||
790 | langwell_otg_HAAR(0); | ||
791 | |||
792 | if (langwell->host_ops) | ||
793 | langwell->host_ops->remove(langwell->pdev); | ||
794 | else | ||
795 | otg_dbg("host driver has been removed.\n"); | ||
796 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
797 | } else if (langwell->hsm.a_conn) { | ||
798 | langwell_otg_del_timer(b_ase0_brst_tmr); | ||
799 | langwell_otg_HAAR(0); | ||
800 | langwell->otg.state = OTG_STATE_B_HOST; | ||
801 | queue_work(langwell->qwork, &langwell->work); | ||
802 | } else if (langwell->hsm.a_bus_resume || | ||
803 | langwell->hsm.b_ase0_brst_tmout) { | ||
804 | langwell_otg_del_timer(b_ase0_brst_tmr); | ||
805 | langwell_otg_HAAR(0); | ||
806 | langwell_otg_nsf_msg(7); | ||
807 | |||
808 | if (langwell->host_ops) | ||
809 | langwell->host_ops->remove(langwell->pdev); | ||
810 | else | ||
811 | otg_dbg("host driver has been removed.\n"); | ||
812 | |||
813 | langwell->hsm.a_bus_suspend = 0; | ||
814 | langwell->hsm.b_bus_req = 0; | ||
815 | |||
816 | if (langwell->client_ops) | ||
817 | langwell->client_ops->resume(langwell->pdev); | ||
818 | else | ||
819 | otg_dbg("client driver not loaded.\n"); | ||
820 | |||
821 | langwell->otg.state = OTG_STATE_B_PERIPHERAL; | ||
822 | } | ||
823 | break; | ||
824 | |||
825 | case OTG_STATE_B_HOST: | ||
826 | if (!langwell->hsm.id) { | ||
827 | langwell->otg.default_a = 1; | ||
828 | langwell->hsm.a_srp_det = 0; | ||
829 | |||
830 | langwell_otg_drv_vbus(0); | ||
831 | langwell_otg_chrg_vbus(0); | ||
832 | set_host_mode(); | ||
833 | if (langwell->host_ops) | ||
834 | langwell->host_ops->remove(langwell->pdev); | ||
835 | else | ||
836 | otg_dbg("host driver has been removed.\n"); | ||
837 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
838 | queue_work(langwell->qwork, &langwell->work); | ||
839 | } else if (!langwell->hsm.b_sess_vld) { | ||
840 | langwell->hsm.b_hnp_enable = 0; | ||
841 | langwell->hsm.b_bus_req = 0; | ||
842 | langwell_otg_chrg_vbus(0); | ||
843 | if (langwell->host_ops) | ||
844 | langwell->host_ops->remove(langwell->pdev); | ||
845 | else | ||
846 | otg_dbg("host driver has been removed.\n"); | ||
847 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
848 | } else if ((!langwell->hsm.b_bus_req) || | ||
849 | (!langwell->hsm.a_conn)) { | ||
850 | langwell->hsm.b_bus_req = 0; | ||
851 | langwell_otg_loc_sof(0); | ||
852 | if (langwell->host_ops) | ||
853 | langwell->host_ops->remove(langwell->pdev); | ||
854 | else | ||
855 | otg_dbg("host driver has been removed.\n"); | ||
856 | |||
857 | langwell->hsm.a_bus_suspend = 0; | ||
858 | |||
859 | if (langwell->client_ops) | ||
860 | langwell->client_ops->resume(langwell->pdev); | ||
861 | else | ||
862 | otg_dbg("client driver not loaded.\n"); | ||
863 | |||
864 | langwell->otg.state = OTG_STATE_B_PERIPHERAL; | ||
865 | } | ||
866 | break; | ||
867 | |||
868 | case OTG_STATE_A_IDLE: | ||
869 | langwell->otg.default_a = 1; | ||
870 | if (langwell->hsm.id) { | ||
871 | langwell->otg.default_a = 0; | ||
872 | langwell->hsm.b_bus_req = 0; | ||
873 | langwell_otg_drv_vbus(0); | ||
874 | langwell_otg_chrg_vbus(0); | ||
875 | |||
876 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
877 | queue_work(langwell->qwork, &langwell->work); | ||
878 | } else if (langwell->hsm.a_sess_vld) { | ||
879 | langwell_otg_drv_vbus(1); | ||
880 | langwell->hsm.a_srp_det = 1; | ||
881 | langwell->hsm.a_wait_vrise_tmout = 0; | ||
882 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
883 | langwell->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
884 | queue_work(langwell->qwork, &langwell->work); | ||
885 | } else if (!langwell->hsm.a_bus_drop && | ||
886 | (langwell->hsm.a_srp_det || langwell->hsm.a_bus_req)) { | ||
887 | langwell_otg_drv_vbus(1); | ||
888 | langwell->hsm.a_wait_vrise_tmout = 0; | ||
889 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
890 | langwell->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
891 | queue_work(langwell->qwork, &langwell->work); | ||
892 | } | ||
893 | break; | ||
894 | case OTG_STATE_A_WAIT_VRISE: | ||
895 | if (langwell->hsm.id) { | ||
896 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
897 | langwell->hsm.b_bus_req = 0; | ||
898 | langwell->otg.default_a = 0; | ||
899 | langwell_otg_drv_vbus(0); | ||
900 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
901 | } else if (langwell->hsm.a_vbus_vld) { | ||
902 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
903 | if (langwell->host_ops) | ||
904 | langwell->host_ops->probe(langwell->pdev, | ||
905 | langwell->host_ops->id_table); | ||
906 | else | ||
907 | otg_dbg("host driver not loaded.\n"); | ||
908 | langwell->hsm.b_conn = 0; | ||
909 | langwell->hsm.a_set_b_hnp_en = 0; | ||
910 | langwell->hsm.a_wait_bcon_tmout = 0; | ||
911 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
912 | langwell->otg.state = OTG_STATE_A_WAIT_BCON; | ||
913 | } else if (langwell->hsm.a_wait_vrise_tmout) { | ||
914 | if (langwell->hsm.a_vbus_vld) { | ||
915 | if (langwell->host_ops) | ||
916 | langwell->host_ops->probe( | ||
917 | langwell->pdev, | ||
918 | langwell->host_ops->id_table); | ||
919 | else | ||
920 | otg_dbg("host driver not loaded.\n"); | ||
921 | langwell->hsm.b_conn = 0; | ||
922 | langwell->hsm.a_set_b_hnp_en = 0; | ||
923 | langwell->hsm.a_wait_bcon_tmout = 0; | ||
924 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
925 | langwell->otg.state = OTG_STATE_A_WAIT_BCON; | ||
926 | } else { | ||
927 | langwell_otg_drv_vbus(0); | ||
928 | langwell->otg.state = OTG_STATE_A_VBUS_ERR; | ||
929 | } | ||
930 | } | ||
931 | break; | ||
932 | case OTG_STATE_A_WAIT_BCON: | ||
933 | if (langwell->hsm.id) { | ||
934 | langwell_otg_del_timer(a_wait_bcon_tmr); | ||
935 | |||
936 | langwell->otg.default_a = 0; | ||
937 | langwell->hsm.b_bus_req = 0; | ||
938 | if (langwell->host_ops) | ||
939 | langwell->host_ops->remove(langwell->pdev); | ||
940 | else | ||
941 | otg_dbg("host driver has been removed.\n"); | ||
942 | langwell_otg_drv_vbus(0); | ||
943 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
944 | queue_work(langwell->qwork, &langwell->work); | ||
945 | } else if (!langwell->hsm.a_vbus_vld) { | ||
946 | langwell_otg_del_timer(a_wait_bcon_tmr); | ||
947 | |||
948 | if (langwell->host_ops) | ||
949 | langwell->host_ops->remove(langwell->pdev); | ||
950 | else | ||
951 | otg_dbg("host driver has been removed.\n"); | ||
952 | langwell_otg_drv_vbus(0); | ||
953 | langwell->otg.state = OTG_STATE_A_VBUS_ERR; | ||
954 | } else if (langwell->hsm.a_bus_drop || | ||
955 | (langwell->hsm.a_wait_bcon_tmout && | ||
956 | !langwell->hsm.a_bus_req)) { | ||
957 | langwell_otg_del_timer(a_wait_bcon_tmr); | ||
958 | |||
959 | if (langwell->host_ops) | ||
960 | langwell->host_ops->remove(langwell->pdev); | ||
961 | else | ||
962 | otg_dbg("host driver has been removed.\n"); | ||
963 | langwell_otg_drv_vbus(0); | ||
964 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
965 | } else if (langwell->hsm.b_conn) { | ||
966 | langwell_otg_del_timer(a_wait_bcon_tmr); | ||
967 | |||
968 | langwell->hsm.a_suspend_req = 0; | ||
969 | langwell->otg.state = OTG_STATE_A_HOST; | ||
970 | if (!langwell->hsm.a_bus_req && | ||
971 | langwell->hsm.a_set_b_hnp_en) { | ||
972 | /* It is not safe enough to do a fast | ||
973 | * transistion from A_WAIT_BCON to | ||
974 | * A_SUSPEND */ | ||
975 | msleep(10000); | ||
976 | if (langwell->hsm.a_bus_req) | ||
977 | break; | ||
978 | |||
979 | if (request_irq(langwell->pdev->irq, | ||
980 | otg_dummy_irq, IRQF_SHARED, | ||
981 | driver_name, langwell->regs) != 0) { | ||
982 | otg_dbg("request interrupt %d fail\n", | ||
983 | langwell->pdev->irq); | ||
984 | } | ||
985 | |||
986 | langwell_otg_HABA(1); | ||
987 | langwell->hsm.b_bus_resume = 0; | ||
988 | langwell->hsm.a_aidl_bdis_tmout = 0; | ||
989 | langwell_otg_add_timer(a_aidl_bdis_tmr); | ||
990 | |||
991 | langwell_otg_loc_sof(0); | ||
992 | langwell->otg.state = OTG_STATE_A_SUSPEND; | ||
993 | } else if (!langwell->hsm.a_bus_req && | ||
994 | !langwell->hsm.a_set_b_hnp_en) { | ||
995 | struct pci_dev *pdev = langwell->pdev; | ||
996 | if (langwell->host_ops) | ||
997 | langwell->host_ops->remove(pdev); | ||
998 | else | ||
999 | otg_dbg("host driver removed.\n"); | ||
1000 | langwell_otg_drv_vbus(0); | ||
1001 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1002 | } | ||
1003 | } | ||
1004 | break; | ||
1005 | case OTG_STATE_A_HOST: | ||
1006 | if (langwell->hsm.id) { | ||
1007 | langwell->otg.default_a = 0; | ||
1008 | langwell->hsm.b_bus_req = 0; | ||
1009 | if (langwell->host_ops) | ||
1010 | langwell->host_ops->remove(langwell->pdev); | ||
1011 | else | ||
1012 | otg_dbg("host driver has been removed.\n"); | ||
1013 | langwell_otg_drv_vbus(0); | ||
1014 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
1015 | queue_work(langwell->qwork, &langwell->work); | ||
1016 | } else if (langwell->hsm.a_bus_drop || | ||
1017 | (!langwell->hsm.a_set_b_hnp_en && !langwell->hsm.a_bus_req)) { | ||
1018 | if (langwell->host_ops) | ||
1019 | langwell->host_ops->remove(langwell->pdev); | ||
1020 | else | ||
1021 | otg_dbg("host driver has been removed.\n"); | ||
1022 | langwell_otg_drv_vbus(0); | ||
1023 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1024 | } else if (!langwell->hsm.a_vbus_vld) { | ||
1025 | if (langwell->host_ops) | ||
1026 | langwell->host_ops->remove(langwell->pdev); | ||
1027 | else | ||
1028 | otg_dbg("host driver has been removed.\n"); | ||
1029 | langwell_otg_drv_vbus(0); | ||
1030 | langwell->otg.state = OTG_STATE_A_VBUS_ERR; | ||
1031 | } else if (langwell->hsm.a_set_b_hnp_en | ||
1032 | && !langwell->hsm.a_bus_req) { | ||
1033 | /* Set HABA to enable hardware assistance to signal | ||
1034 | * A-connect after receiver B-disconnect. Hardware | ||
1035 | * will then set client mode and enable URE, SLE and | ||
1036 | * PCE after the assistance. otg_dummy_irq is used to | ||
1037 | * clean these ints when client driver is not resumed. | ||
1038 | */ | ||
1039 | if (request_irq(langwell->pdev->irq, | ||
1040 | otg_dummy_irq, IRQF_SHARED, driver_name, | ||
1041 | langwell->regs) != 0) { | ||
1042 | otg_dbg("request interrupt %d failed\n", | ||
1043 | langwell->pdev->irq); | ||
1044 | } | ||
1045 | |||
1046 | /* set HABA */ | ||
1047 | langwell_otg_HABA(1); | ||
1048 | langwell->hsm.b_bus_resume = 0; | ||
1049 | langwell->hsm.a_aidl_bdis_tmout = 0; | ||
1050 | langwell_otg_add_timer(a_aidl_bdis_tmr); | ||
1051 | langwell_otg_loc_sof(0); | ||
1052 | langwell->otg.state = OTG_STATE_A_SUSPEND; | ||
1053 | } else if (!langwell->hsm.b_conn || !langwell->hsm.a_bus_req) { | ||
1054 | langwell->hsm.a_wait_bcon_tmout = 0; | ||
1055 | langwell->hsm.a_set_b_hnp_en = 0; | ||
1056 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
1057 | langwell->otg.state = OTG_STATE_A_WAIT_BCON; | ||
1058 | } | ||
1059 | break; | ||
1060 | case OTG_STATE_A_SUSPEND: | ||
1061 | if (langwell->hsm.id) { | ||
1062 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1063 | langwell_otg_HABA(0); | ||
1064 | free_irq(langwell->pdev->irq, langwell->regs); | ||
1065 | langwell->otg.default_a = 0; | ||
1066 | langwell->hsm.b_bus_req = 0; | ||
1067 | if (langwell->host_ops) | ||
1068 | langwell->host_ops->remove(langwell->pdev); | ||
1069 | else | ||
1070 | otg_dbg("host driver has been removed.\n"); | ||
1071 | langwell_otg_drv_vbus(0); | ||
1072 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
1073 | queue_work(langwell->qwork, &langwell->work); | ||
1074 | } else if (langwell->hsm.a_bus_req || | ||
1075 | langwell->hsm.b_bus_resume) { | ||
1076 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1077 | langwell_otg_HABA(0); | ||
1078 | free_irq(langwell->pdev->irq, langwell->regs); | ||
1079 | langwell->hsm.a_suspend_req = 0; | ||
1080 | langwell_otg_loc_sof(1); | ||
1081 | langwell->otg.state = OTG_STATE_A_HOST; | ||
1082 | } else if (langwell->hsm.a_aidl_bdis_tmout || | ||
1083 | langwell->hsm.a_bus_drop) { | ||
1084 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1085 | langwell_otg_HABA(0); | ||
1086 | free_irq(langwell->pdev->irq, langwell->regs); | ||
1087 | if (langwell->host_ops) | ||
1088 | langwell->host_ops->remove(langwell->pdev); | ||
1089 | else | ||
1090 | otg_dbg("host driver has been removed.\n"); | ||
1091 | langwell_otg_drv_vbus(0); | ||
1092 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1093 | } else if (!langwell->hsm.b_conn && | ||
1094 | langwell->hsm.a_set_b_hnp_en) { | ||
1095 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1096 | langwell_otg_HABA(0); | ||
1097 | free_irq(langwell->pdev->irq, langwell->regs); | ||
1098 | |||
1099 | if (langwell->host_ops) | ||
1100 | langwell->host_ops->remove(langwell->pdev); | ||
1101 | else | ||
1102 | otg_dbg("host driver has been removed.\n"); | ||
1103 | |||
1104 | langwell->hsm.b_bus_suspend = 0; | ||
1105 | langwell->hsm.b_bus_suspend_vld = 0; | ||
1106 | langwell->hsm.b_bus_suspend_tmout = 0; | ||
1107 | |||
1108 | /* msleep(200); */ | ||
1109 | if (langwell->client_ops) | ||
1110 | langwell->client_ops->resume(langwell->pdev); | ||
1111 | else | ||
1112 | otg_dbg("client driver not loaded.\n"); | ||
1113 | |||
1114 | langwell_otg_add_timer(b_bus_suspend_tmr); | ||
1115 | langwell->otg.state = OTG_STATE_A_PERIPHERAL; | ||
1116 | break; | ||
1117 | } else if (!langwell->hsm.a_vbus_vld) { | ||
1118 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1119 | langwell_otg_HABA(0); | ||
1120 | free_irq(langwell->pdev->irq, langwell->regs); | ||
1121 | if (langwell->host_ops) | ||
1122 | langwell->host_ops->remove(langwell->pdev); | ||
1123 | else | ||
1124 | otg_dbg("host driver has been removed.\n"); | ||
1125 | langwell_otg_drv_vbus(0); | ||
1126 | langwell->otg.state = OTG_STATE_A_VBUS_ERR; | ||
1127 | } | ||
1128 | break; | ||
1129 | case OTG_STATE_A_PERIPHERAL: | ||
1130 | if (langwell->hsm.id) { | ||
1131 | langwell_otg_del_timer(b_bus_suspend_tmr); | ||
1132 | langwell->otg.default_a = 0; | ||
1133 | langwell->hsm.b_bus_req = 0; | ||
1134 | if (langwell->client_ops) | ||
1135 | langwell->client_ops->suspend(langwell->pdev, | ||
1136 | PMSG_FREEZE); | ||
1137 | else | ||
1138 | otg_dbg("client driver has been removed.\n"); | ||
1139 | langwell_otg_drv_vbus(0); | ||
1140 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
1141 | queue_work(langwell->qwork, &langwell->work); | ||
1142 | } else if (!langwell->hsm.a_vbus_vld) { | ||
1143 | langwell_otg_del_timer(b_bus_suspend_tmr); | ||
1144 | if (langwell->client_ops) | ||
1145 | langwell->client_ops->suspend(langwell->pdev, | ||
1146 | PMSG_FREEZE); | ||
1147 | else | ||
1148 | otg_dbg("client driver has been removed.\n"); | ||
1149 | langwell_otg_drv_vbus(0); | ||
1150 | langwell->otg.state = OTG_STATE_A_VBUS_ERR; | ||
1151 | } else if (langwell->hsm.a_bus_drop) { | ||
1152 | langwell_otg_del_timer(b_bus_suspend_tmr); | ||
1153 | if (langwell->client_ops) | ||
1154 | langwell->client_ops->suspend(langwell->pdev, | ||
1155 | PMSG_FREEZE); | ||
1156 | else | ||
1157 | otg_dbg("client driver has been removed.\n"); | ||
1158 | langwell_otg_drv_vbus(0); | ||
1159 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1160 | } else if (langwell->hsm.b_bus_suspend) { | ||
1161 | langwell_otg_del_timer(b_bus_suspend_tmr); | ||
1162 | if (langwell->client_ops) | ||
1163 | langwell->client_ops->suspend(langwell->pdev, | ||
1164 | PMSG_FREEZE); | ||
1165 | else | ||
1166 | otg_dbg("client driver has been removed.\n"); | ||
1167 | |||
1168 | if (langwell->host_ops) | ||
1169 | langwell->host_ops->probe(langwell->pdev, | ||
1170 | langwell->host_ops->id_table); | ||
1171 | else | ||
1172 | otg_dbg("host driver not loaded.\n"); | ||
1173 | langwell->hsm.a_set_b_hnp_en = 0; | ||
1174 | langwell->hsm.a_wait_bcon_tmout = 0; | ||
1175 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
1176 | langwell->otg.state = OTG_STATE_A_WAIT_BCON; | ||
1177 | } else if (langwell->hsm.b_bus_suspend_tmout) { | ||
1178 | u32 val; | ||
1179 | val = readl(langwell->regs + CI_PORTSC1); | ||
1180 | if (!(val & PORTSC_SUSP)) | ||
1181 | break; | ||
1182 | if (langwell->client_ops) | ||
1183 | langwell->client_ops->suspend(langwell->pdev, | ||
1184 | PMSG_FREEZE); | ||
1185 | else | ||
1186 | otg_dbg("client driver has been removed.\n"); | ||
1187 | if (langwell->host_ops) | ||
1188 | langwell->host_ops->probe(langwell->pdev, | ||
1189 | langwell->host_ops->id_table); | ||
1190 | else | ||
1191 | otg_dbg("host driver not loaded.\n"); | ||
1192 | langwell->hsm.a_set_b_hnp_en = 0; | ||
1193 | langwell->hsm.a_wait_bcon_tmout = 0; | ||
1194 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
1195 | langwell->otg.state = OTG_STATE_A_WAIT_BCON; | ||
1196 | } | ||
1197 | break; | ||
1198 | case OTG_STATE_A_VBUS_ERR: | ||
1199 | if (langwell->hsm.id) { | ||
1200 | langwell->otg.default_a = 0; | ||
1201 | langwell->hsm.a_clr_err = 0; | ||
1202 | langwell->hsm.a_srp_det = 0; | ||
1203 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
1204 | queue_work(langwell->qwork, &langwell->work); | ||
1205 | } else if (langwell->hsm.a_clr_err) { | ||
1206 | langwell->hsm.a_clr_err = 0; | ||
1207 | langwell->hsm.a_srp_det = 0; | ||
1208 | reset_otg(); | ||
1209 | init_hsm(); | ||
1210 | if (langwell->otg.state == OTG_STATE_A_IDLE) | ||
1211 | queue_work(langwell->qwork, &langwell->work); | ||
1212 | } | ||
1213 | break; | ||
1214 | case OTG_STATE_A_WAIT_VFALL: | ||
1215 | if (langwell->hsm.id) { | ||
1216 | langwell->otg.default_a = 0; | ||
1217 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
1218 | queue_work(langwell->qwork, &langwell->work); | ||
1219 | } else if (langwell->hsm.a_bus_req) { | ||
1220 | langwell_otg_drv_vbus(1); | ||
1221 | langwell->hsm.a_wait_vrise_tmout = 0; | ||
1222 | langwell_otg_add_timer(a_wait_vrise_tmr); | ||
1223 | langwell->otg.state = OTG_STATE_A_WAIT_VRISE; | ||
1224 | } else if (!langwell->hsm.a_sess_vld) { | ||
1225 | langwell->hsm.a_srp_det = 0; | ||
1226 | langwell_otg_drv_vbus(0); | ||
1227 | set_host_mode(); | ||
1228 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
1229 | } | ||
1230 | break; | ||
1231 | default: | ||
1232 | ; | ||
1233 | } | ||
1234 | |||
1235 | otg_dbg("%s: new state = %s\n", __func__, | ||
1236 | state_string(langwell->otg.state)); | ||
1237 | } | ||
1238 | |||
1239 | static ssize_t | ||
1240 | show_registers(struct device *_dev, struct device_attribute *attr, char *buf) | ||
1241 | { | ||
1242 | struct langwell_otg *langwell; | ||
1243 | char *next; | ||
1244 | unsigned size; | ||
1245 | unsigned t; | ||
1246 | |||
1247 | langwell = the_transceiver; | ||
1248 | next = buf; | ||
1249 | size = PAGE_SIZE; | ||
1250 | |||
1251 | t = scnprintf(next, size, | ||
1252 | "\n" | ||
1253 | "USBCMD = 0x%08x \n" | ||
1254 | "USBSTS = 0x%08x \n" | ||
1255 | "USBINTR = 0x%08x \n" | ||
1256 | "ASYNCLISTADDR = 0x%08x \n" | ||
1257 | "PORTSC1 = 0x%08x \n" | ||
1258 | "HOSTPC1 = 0x%08x \n" | ||
1259 | "OTGSC = 0x%08x \n" | ||
1260 | "USBMODE = 0x%08x \n", | ||
1261 | readl(langwell->regs + 0x30), | ||
1262 | readl(langwell->regs + 0x34), | ||
1263 | readl(langwell->regs + 0x38), | ||
1264 | readl(langwell->regs + 0x48), | ||
1265 | readl(langwell->regs + 0x74), | ||
1266 | readl(langwell->regs + 0xb4), | ||
1267 | readl(langwell->regs + 0xf4), | ||
1268 | readl(langwell->regs + 0xf8) | ||
1269 | ); | ||
1270 | size -= t; | ||
1271 | next += t; | ||
1272 | |||
1273 | return PAGE_SIZE - size; | ||
1274 | } | ||
1275 | static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); | ||
1276 | |||
1277 | static ssize_t | ||
1278 | show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) | ||
1279 | { | ||
1280 | struct langwell_otg *langwell; | ||
1281 | char *next; | ||
1282 | unsigned size; | ||
1283 | unsigned t; | ||
1284 | |||
1285 | langwell = the_transceiver; | ||
1286 | next = buf; | ||
1287 | size = PAGE_SIZE; | ||
1288 | |||
1289 | t = scnprintf(next, size, | ||
1290 | "\n" | ||
1291 | "current state = %s\n" | ||
1292 | "a_bus_resume = \t%d\n" | ||
1293 | "a_bus_suspend = \t%d\n" | ||
1294 | "a_conn = \t%d\n" | ||
1295 | "a_sess_vld = \t%d\n" | ||
1296 | "a_srp_det = \t%d\n" | ||
1297 | "a_vbus_vld = \t%d\n" | ||
1298 | "b_bus_resume = \t%d\n" | ||
1299 | "b_bus_suspend = \t%d\n" | ||
1300 | "b_conn = \t%d\n" | ||
1301 | "b_se0_srp = \t%d\n" | ||
1302 | "b_sess_end = \t%d\n" | ||
1303 | "b_sess_vld = \t%d\n" | ||
1304 | "id = \t%d\n" | ||
1305 | "a_set_b_hnp_en = \t%d\n" | ||
1306 | "b_srp_done = \t%d\n" | ||
1307 | "b_hnp_enable = \t%d\n" | ||
1308 | "a_wait_vrise_tmout = \t%d\n" | ||
1309 | "a_wait_bcon_tmout = \t%d\n" | ||
1310 | "a_aidl_bdis_tmout = \t%d\n" | ||
1311 | "b_ase0_brst_tmout = \t%d\n" | ||
1312 | "a_bus_drop = \t%d\n" | ||
1313 | "a_bus_req = \t%d\n" | ||
1314 | "a_clr_err = \t%d\n" | ||
1315 | "a_suspend_req = \t%d\n" | ||
1316 | "b_bus_req = \t%d\n" | ||
1317 | "b_bus_suspend_tmout = \t%d\n" | ||
1318 | "b_bus_suspend_vld = \t%d\n", | ||
1319 | state_string(langwell->otg.state), | ||
1320 | langwell->hsm.a_bus_resume, | ||
1321 | langwell->hsm.a_bus_suspend, | ||
1322 | langwell->hsm.a_conn, | ||
1323 | langwell->hsm.a_sess_vld, | ||
1324 | langwell->hsm.a_srp_det, | ||
1325 | langwell->hsm.a_vbus_vld, | ||
1326 | langwell->hsm.b_bus_resume, | ||
1327 | langwell->hsm.b_bus_suspend, | ||
1328 | langwell->hsm.b_conn, | ||
1329 | langwell->hsm.b_se0_srp, | ||
1330 | langwell->hsm.b_sess_end, | ||
1331 | langwell->hsm.b_sess_vld, | ||
1332 | langwell->hsm.id, | ||
1333 | langwell->hsm.a_set_b_hnp_en, | ||
1334 | langwell->hsm.b_srp_done, | ||
1335 | langwell->hsm.b_hnp_enable, | ||
1336 | langwell->hsm.a_wait_vrise_tmout, | ||
1337 | langwell->hsm.a_wait_bcon_tmout, | ||
1338 | langwell->hsm.a_aidl_bdis_tmout, | ||
1339 | langwell->hsm.b_ase0_brst_tmout, | ||
1340 | langwell->hsm.a_bus_drop, | ||
1341 | langwell->hsm.a_bus_req, | ||
1342 | langwell->hsm.a_clr_err, | ||
1343 | langwell->hsm.a_suspend_req, | ||
1344 | langwell->hsm.b_bus_req, | ||
1345 | langwell->hsm.b_bus_suspend_tmout, | ||
1346 | langwell->hsm.b_bus_suspend_vld | ||
1347 | ); | ||
1348 | size -= t; | ||
1349 | next += t; | ||
1350 | |||
1351 | return PAGE_SIZE - size; | ||
1352 | } | ||
1353 | static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL); | ||
1354 | |||
1355 | static ssize_t | ||
1356 | get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | ||
1357 | { | ||
1358 | struct langwell_otg *langwell; | ||
1359 | char *next; | ||
1360 | unsigned size; | ||
1361 | unsigned t; | ||
1362 | |||
1363 | langwell = the_transceiver; | ||
1364 | next = buf; | ||
1365 | size = PAGE_SIZE; | ||
1366 | |||
1367 | t = scnprintf(next, size, "%d", langwell->hsm.a_bus_req); | ||
1368 | size -= t; | ||
1369 | next += t; | ||
1370 | |||
1371 | return PAGE_SIZE - size; | ||
1372 | } | ||
1373 | |||
1374 | static ssize_t | ||
1375 | set_a_bus_req(struct device *dev, struct device_attribute *attr, | ||
1376 | const char *buf, size_t count) | ||
1377 | { | ||
1378 | struct langwell_otg *langwell; | ||
1379 | langwell = the_transceiver; | ||
1380 | if (!langwell->otg.default_a) | ||
1381 | return -1; | ||
1382 | if (count > 2) | ||
1383 | return -1; | ||
1384 | |||
1385 | if (buf[0] == '0') { | ||
1386 | langwell->hsm.a_bus_req = 0; | ||
1387 | otg_dbg("a_bus_req = 0\n"); | ||
1388 | } else if (buf[0] == '1') { | ||
1389 | /* If a_bus_drop is TRUE, a_bus_req can't be set */ | ||
1390 | if (langwell->hsm.a_bus_drop) | ||
1391 | return -1; | ||
1392 | langwell->hsm.a_bus_req = 1; | ||
1393 | otg_dbg("a_bus_req = 1\n"); | ||
1394 | } | ||
1395 | if (spin_trylock(&langwell->wq_lock)) { | ||
1396 | queue_work(langwell->qwork, &langwell->work); | ||
1397 | spin_unlock(&langwell->wq_lock); | ||
1398 | } | ||
1399 | return count; | ||
1400 | } | ||
1401 | static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req); | ||
1402 | |||
1403 | static ssize_t | ||
1404 | get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf) | ||
1405 | { | ||
1406 | struct langwell_otg *langwell; | ||
1407 | char *next; | ||
1408 | unsigned size; | ||
1409 | unsigned t; | ||
1410 | |||
1411 | langwell = the_transceiver; | ||
1412 | next = buf; | ||
1413 | size = PAGE_SIZE; | ||
1414 | |||
1415 | t = scnprintf(next, size, "%d", langwell->hsm.a_bus_drop); | ||
1416 | size -= t; | ||
1417 | next += t; | ||
1418 | |||
1419 | return PAGE_SIZE - size; | ||
1420 | } | ||
1421 | |||
1422 | static ssize_t | ||
1423 | set_a_bus_drop(struct device *dev, struct device_attribute *attr, | ||
1424 | const char *buf, size_t count) | ||
1425 | { | ||
1426 | struct langwell_otg *langwell; | ||
1427 | langwell = the_transceiver; | ||
1428 | if (!langwell->otg.default_a) | ||
1429 | return -1; | ||
1430 | if (count > 2) | ||
1431 | return -1; | ||
1432 | |||
1433 | if (buf[0] == '0') { | ||
1434 | langwell->hsm.a_bus_drop = 0; | ||
1435 | otg_dbg("a_bus_drop = 0\n"); | ||
1436 | } else if (buf[0] == '1') { | ||
1437 | langwell->hsm.a_bus_drop = 1; | ||
1438 | langwell->hsm.a_bus_req = 0; | ||
1439 | otg_dbg("a_bus_drop = 1, then a_bus_req = 0\n"); | ||
1440 | } | ||
1441 | if (spin_trylock(&langwell->wq_lock)) { | ||
1442 | queue_work(langwell->qwork, &langwell->work); | ||
1443 | spin_unlock(&langwell->wq_lock); | ||
1444 | } | ||
1445 | return count; | ||
1446 | } | ||
1447 | static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO, | ||
1448 | get_a_bus_drop, set_a_bus_drop); | ||
1449 | |||
1450 | static ssize_t | ||
1451 | get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | ||
1452 | { | ||
1453 | struct langwell_otg *langwell; | ||
1454 | char *next; | ||
1455 | unsigned size; | ||
1456 | unsigned t; | ||
1457 | |||
1458 | langwell = the_transceiver; | ||
1459 | next = buf; | ||
1460 | size = PAGE_SIZE; | ||
1461 | |||
1462 | t = scnprintf(next, size, "%d", langwell->hsm.b_bus_req); | ||
1463 | size -= t; | ||
1464 | next += t; | ||
1465 | |||
1466 | return PAGE_SIZE - size; | ||
1467 | } | ||
1468 | |||
1469 | static ssize_t | ||
1470 | set_b_bus_req(struct device *dev, struct device_attribute *attr, | ||
1471 | const char *buf, size_t count) | ||
1472 | { | ||
1473 | struct langwell_otg *langwell; | ||
1474 | langwell = the_transceiver; | ||
1475 | |||
1476 | if (langwell->otg.default_a) | ||
1477 | return -1; | ||
1478 | |||
1479 | if (count > 2) | ||
1480 | return -1; | ||
1481 | |||
1482 | if (buf[0] == '0') { | ||
1483 | langwell->hsm.b_bus_req = 0; | ||
1484 | otg_dbg("b_bus_req = 0\n"); | ||
1485 | } else if (buf[0] == '1') { | ||
1486 | langwell->hsm.b_bus_req = 1; | ||
1487 | otg_dbg("b_bus_req = 1\n"); | ||
1488 | } | ||
1489 | if (spin_trylock(&langwell->wq_lock)) { | ||
1490 | queue_work(langwell->qwork, &langwell->work); | ||
1491 | spin_unlock(&langwell->wq_lock); | ||
1492 | } | ||
1493 | return count; | ||
1494 | } | ||
1495 | static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req); | ||
1496 | |||
1497 | static ssize_t | ||
1498 | set_a_clr_err(struct device *dev, struct device_attribute *attr, | ||
1499 | const char *buf, size_t count) | ||
1500 | { | ||
1501 | struct langwell_otg *langwell; | ||
1502 | langwell = the_transceiver; | ||
1503 | |||
1504 | if (!langwell->otg.default_a) | ||
1505 | return -1; | ||
1506 | if (count > 2) | ||
1507 | return -1; | ||
1508 | |||
1509 | if (buf[0] == '1') { | ||
1510 | langwell->hsm.a_clr_err = 1; | ||
1511 | otg_dbg("a_clr_err = 1\n"); | ||
1512 | } | ||
1513 | if (spin_trylock(&langwell->wq_lock)) { | ||
1514 | queue_work(langwell->qwork, &langwell->work); | ||
1515 | spin_unlock(&langwell->wq_lock); | ||
1516 | } | ||
1517 | return count; | ||
1518 | } | ||
1519 | static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err); | ||
1520 | |||
1521 | static struct attribute *inputs_attrs[] = { | ||
1522 | &dev_attr_a_bus_req.attr, | ||
1523 | &dev_attr_a_bus_drop.attr, | ||
1524 | &dev_attr_b_bus_req.attr, | ||
1525 | &dev_attr_a_clr_err.attr, | ||
1526 | NULL, | ||
1527 | }; | ||
1528 | |||
1529 | static struct attribute_group debug_dev_attr_group = { | ||
1530 | .name = "inputs", | ||
1531 | .attrs = inputs_attrs, | ||
1532 | }; | ||
1533 | |||
1534 | int langwell_register_host(struct pci_driver *host_driver) | ||
1535 | { | ||
1536 | int ret = 0; | ||
1537 | |||
1538 | the_transceiver->host_ops = host_driver; | ||
1539 | queue_work(the_transceiver->qwork, &the_transceiver->work); | ||
1540 | otg_dbg("host controller driver is registered\n"); | ||
1541 | |||
1542 | return ret; | ||
1543 | } | ||
1544 | EXPORT_SYMBOL(langwell_register_host); | ||
1545 | |||
1546 | void langwell_unregister_host(struct pci_driver *host_driver) | ||
1547 | { | ||
1548 | if (the_transceiver->host_ops) | ||
1549 | the_transceiver->host_ops->remove(the_transceiver->pdev); | ||
1550 | the_transceiver->host_ops = NULL; | ||
1551 | the_transceiver->hsm.a_bus_drop = 1; | ||
1552 | queue_work(the_transceiver->qwork, &the_transceiver->work); | ||
1553 | otg_dbg("host controller driver is unregistered\n"); | ||
1554 | } | ||
1555 | EXPORT_SYMBOL(langwell_unregister_host); | ||
1556 | |||
1557 | int langwell_register_peripheral(struct pci_driver *client_driver) | ||
1558 | { | ||
1559 | int ret = 0; | ||
1560 | |||
1561 | if (client_driver) | ||
1562 | ret = client_driver->probe(the_transceiver->pdev, | ||
1563 | client_driver->id_table); | ||
1564 | if (!ret) { | ||
1565 | the_transceiver->client_ops = client_driver; | ||
1566 | queue_work(the_transceiver->qwork, &the_transceiver->work); | ||
1567 | otg_dbg("client controller driver is registered\n"); | ||
1568 | } | ||
1569 | |||
1570 | return ret; | ||
1571 | } | ||
1572 | EXPORT_SYMBOL(langwell_register_peripheral); | ||
1573 | |||
1574 | void langwell_unregister_peripheral(struct pci_driver *client_driver) | ||
1575 | { | ||
1576 | if (the_transceiver->client_ops) | ||
1577 | the_transceiver->client_ops->remove(the_transceiver->pdev); | ||
1578 | the_transceiver->client_ops = NULL; | ||
1579 | the_transceiver->hsm.b_bus_req = 0; | ||
1580 | queue_work(the_transceiver->qwork, &the_transceiver->work); | ||
1581 | otg_dbg("client controller driver is unregistered\n"); | ||
1582 | } | ||
1583 | EXPORT_SYMBOL(langwell_unregister_peripheral); | ||
1584 | |||
1585 | static int langwell_otg_probe(struct pci_dev *pdev, | ||
1586 | const struct pci_device_id *id) | ||
1587 | { | ||
1588 | unsigned long resource, len; | ||
1589 | void __iomem *base = NULL; | ||
1590 | int retval; | ||
1591 | u32 val32; | ||
1592 | struct langwell_otg *langwell; | ||
1593 | char qname[] = "langwell_otg_queue"; | ||
1594 | |||
1595 | retval = 0; | ||
1596 | otg_dbg("\notg controller is detected.\n"); | ||
1597 | if (pci_enable_device(pdev) < 0) { | ||
1598 | retval = -ENODEV; | ||
1599 | goto done; | ||
1600 | } | ||
1601 | |||
1602 | langwell = kzalloc(sizeof *langwell, GFP_KERNEL); | ||
1603 | if (langwell == NULL) { | ||
1604 | retval = -ENOMEM; | ||
1605 | goto done; | ||
1606 | } | ||
1607 | the_transceiver = langwell; | ||
1608 | |||
1609 | /* control register: BAR 0 */ | ||
1610 | resource = pci_resource_start(pdev, 0); | ||
1611 | len = pci_resource_len(pdev, 0); | ||
1612 | if (!request_mem_region(resource, len, driver_name)) { | ||
1613 | retval = -EBUSY; | ||
1614 | goto err; | ||
1615 | } | ||
1616 | langwell->region = 1; | ||
1617 | |||
1618 | base = ioremap_nocache(resource, len); | ||
1619 | if (base == NULL) { | ||
1620 | retval = -EFAULT; | ||
1621 | goto err; | ||
1622 | } | ||
1623 | langwell->regs = base; | ||
1624 | |||
1625 | if (!pdev->irq) { | ||
1626 | otg_dbg("No IRQ.\n"); | ||
1627 | retval = -ENODEV; | ||
1628 | goto err; | ||
1629 | } | ||
1630 | |||
1631 | langwell->qwork = create_workqueue(qname); | ||
1632 | if (!langwell->qwork) { | ||
1633 | otg_dbg("cannot create workqueue %s\n", qname); | ||
1634 | retval = -ENOMEM; | ||
1635 | goto err; | ||
1636 | } | ||
1637 | INIT_WORK(&langwell->work, langwell_otg_work); | ||
1638 | |||
1639 | /* OTG common part */ | ||
1640 | langwell->pdev = pdev; | ||
1641 | langwell->otg.dev = &pdev->dev; | ||
1642 | langwell->otg.label = driver_name; | ||
1643 | langwell->otg.set_host = langwell_otg_set_host; | ||
1644 | langwell->otg.set_peripheral = langwell_otg_set_peripheral; | ||
1645 | langwell->otg.set_power = langwell_otg_set_power; | ||
1646 | langwell->otg.start_srp = langwell_otg_start_srp; | ||
1647 | langwell->otg.state = OTG_STATE_UNDEFINED; | ||
1648 | if (otg_set_transceiver(&langwell->otg)) { | ||
1649 | otg_dbg("can't set transceiver\n"); | ||
1650 | retval = -EBUSY; | ||
1651 | goto err; | ||
1652 | } | ||
1653 | |||
1654 | reset_otg(); | ||
1655 | init_hsm(); | ||
1656 | |||
1657 | spin_lock_init(&langwell->lock); | ||
1658 | spin_lock_init(&langwell->wq_lock); | ||
1659 | INIT_LIST_HEAD(&active_timers); | ||
1660 | langwell_otg_init_timers(&langwell->hsm); | ||
1661 | |||
1662 | if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, | ||
1663 | driver_name, langwell) != 0) { | ||
1664 | otg_dbg("request interrupt %d failed\n", pdev->irq); | ||
1665 | retval = -EBUSY; | ||
1666 | goto err; | ||
1667 | } | ||
1668 | |||
1669 | /* enable OTGSC int */ | ||
1670 | val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE | | ||
1671 | OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU; | ||
1672 | writel(val32, langwell->regs + CI_OTGSC); | ||
1673 | |||
1674 | retval = device_create_file(&pdev->dev, &dev_attr_registers); | ||
1675 | if (retval < 0) { | ||
1676 | otg_dbg("Can't register sysfs attribute: %d\n", retval); | ||
1677 | goto err; | ||
1678 | } | ||
1679 | |||
1680 | retval = device_create_file(&pdev->dev, &dev_attr_hsm); | ||
1681 | if (retval < 0) { | ||
1682 | otg_dbg("Can't hsm sysfs attribute: %d\n", retval); | ||
1683 | goto err; | ||
1684 | } | ||
1685 | |||
1686 | retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group); | ||
1687 | if (retval < 0) { | ||
1688 | otg_dbg("Can't register sysfs attr group: %d\n", retval); | ||
1689 | goto err; | ||
1690 | } | ||
1691 | |||
1692 | if (langwell->otg.state == OTG_STATE_A_IDLE) | ||
1693 | queue_work(langwell->qwork, &langwell->work); | ||
1694 | |||
1695 | return 0; | ||
1696 | |||
1697 | err: | ||
1698 | if (the_transceiver) | ||
1699 | langwell_otg_remove(pdev); | ||
1700 | done: | ||
1701 | return retval; | ||
1702 | } | ||
1703 | |||
1704 | static void langwell_otg_remove(struct pci_dev *pdev) | ||
1705 | { | ||
1706 | struct langwell_otg *langwell; | ||
1707 | |||
1708 | langwell = the_transceiver; | ||
1709 | |||
1710 | if (langwell->qwork) { | ||
1711 | flush_workqueue(langwell->qwork); | ||
1712 | destroy_workqueue(langwell->qwork); | ||
1713 | } | ||
1714 | langwell_otg_free_timers(); | ||
1715 | |||
1716 | /* disable OTGSC interrupt as OTGSC doesn't change in reset */ | ||
1717 | writel(0, langwell->regs + CI_OTGSC); | ||
1718 | |||
1719 | if (pdev->irq) | ||
1720 | free_irq(pdev->irq, langwell); | ||
1721 | if (langwell->regs) | ||
1722 | iounmap(langwell->regs); | ||
1723 | if (langwell->region) | ||
1724 | release_mem_region(pci_resource_start(pdev, 0), | ||
1725 | pci_resource_len(pdev, 0)); | ||
1726 | |||
1727 | otg_set_transceiver(NULL); | ||
1728 | pci_disable_device(pdev); | ||
1729 | sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group); | ||
1730 | device_remove_file(&pdev->dev, &dev_attr_hsm); | ||
1731 | device_remove_file(&pdev->dev, &dev_attr_registers); | ||
1732 | kfree(langwell); | ||
1733 | langwell = NULL; | ||
1734 | } | ||
1735 | |||
1736 | static void transceiver_suspend(struct pci_dev *pdev) | ||
1737 | { | ||
1738 | pci_save_state(pdev); | ||
1739 | pci_set_power_state(pdev, PCI_D3hot); | ||
1740 | langwell_otg_phy_low_power(1); | ||
1741 | } | ||
1742 | |||
1743 | static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) | ||
1744 | { | ||
1745 | int ret = 0; | ||
1746 | struct langwell_otg *langwell; | ||
1747 | |||
1748 | langwell = the_transceiver; | ||
1749 | |||
1750 | /* Disbale OTG interrupts */ | ||
1751 | langwell_otg_intr(0); | ||
1752 | |||
1753 | if (pdev->irq) | ||
1754 | free_irq(pdev->irq, langwell); | ||
1755 | |||
1756 | /* Prevent more otg_work */ | ||
1757 | flush_workqueue(langwell->qwork); | ||
1758 | spin_lock(&langwell->wq_lock); | ||
1759 | |||
1760 | /* start actions */ | ||
1761 | switch (langwell->otg.state) { | ||
1762 | case OTG_STATE_A_IDLE: | ||
1763 | case OTG_STATE_B_IDLE: | ||
1764 | case OTG_STATE_A_WAIT_VFALL: | ||
1765 | case OTG_STATE_A_VBUS_ERR: | ||
1766 | transceiver_suspend(pdev); | ||
1767 | break; | ||
1768 | case OTG_STATE_A_WAIT_VRISE: | ||
1769 | langwell_otg_del_timer(a_wait_vrise_tmr); | ||
1770 | langwell->hsm.a_srp_det = 0; | ||
1771 | langwell_otg_drv_vbus(0); | ||
1772 | langwell->otg.state = OTG_STATE_A_IDLE; | ||
1773 | transceiver_suspend(pdev); | ||
1774 | break; | ||
1775 | case OTG_STATE_A_WAIT_BCON: | ||
1776 | langwell_otg_del_timer(a_wait_bcon_tmr); | ||
1777 | if (langwell->host_ops) | ||
1778 | ret = langwell->host_ops->suspend(pdev, message); | ||
1779 | langwell_otg_drv_vbus(0); | ||
1780 | break; | ||
1781 | case OTG_STATE_A_HOST: | ||
1782 | if (langwell->host_ops) | ||
1783 | ret = langwell->host_ops->suspend(pdev, message); | ||
1784 | langwell_otg_drv_vbus(0); | ||
1785 | langwell_otg_phy_low_power(1); | ||
1786 | break; | ||
1787 | case OTG_STATE_A_SUSPEND: | ||
1788 | langwell_otg_del_timer(a_aidl_bdis_tmr); | ||
1789 | langwell_otg_HABA(0); | ||
1790 | if (langwell->host_ops) | ||
1791 | langwell->host_ops->remove(pdev); | ||
1792 | else | ||
1793 | otg_dbg("host driver has been removed.\n"); | ||
1794 | langwell_otg_drv_vbus(0); | ||
1795 | transceiver_suspend(pdev); | ||
1796 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1797 | break; | ||
1798 | case OTG_STATE_A_PERIPHERAL: | ||
1799 | if (langwell->client_ops) | ||
1800 | ret = langwell->client_ops->suspend(pdev, message); | ||
1801 | else | ||
1802 | otg_dbg("client driver has been removed.\n"); | ||
1803 | langwell_otg_drv_vbus(0); | ||
1804 | transceiver_suspend(pdev); | ||
1805 | langwell->otg.state = OTG_STATE_A_WAIT_VFALL; | ||
1806 | break; | ||
1807 | case OTG_STATE_B_HOST: | ||
1808 | if (langwell->host_ops) | ||
1809 | langwell->host_ops->remove(pdev); | ||
1810 | else | ||
1811 | otg_dbg("host driver has been removed.\n"); | ||
1812 | langwell->hsm.b_bus_req = 0; | ||
1813 | transceiver_suspend(pdev); | ||
1814 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
1815 | break; | ||
1816 | case OTG_STATE_B_PERIPHERAL: | ||
1817 | if (langwell->client_ops) | ||
1818 | ret = langwell->client_ops->suspend(pdev, message); | ||
1819 | else | ||
1820 | otg_dbg("client driver has been removed.\n"); | ||
1821 | break; | ||
1822 | case OTG_STATE_B_WAIT_ACON: | ||
1823 | langwell_otg_del_timer(b_ase0_brst_tmr); | ||
1824 | langwell_otg_HAAR(0); | ||
1825 | if (langwell->host_ops) | ||
1826 | langwell->host_ops->remove(pdev); | ||
1827 | else | ||
1828 | otg_dbg("host driver has been removed.\n"); | ||
1829 | langwell->hsm.b_bus_req = 0; | ||
1830 | langwell->otg.state = OTG_STATE_B_IDLE; | ||
1831 | transceiver_suspend(pdev); | ||
1832 | break; | ||
1833 | default: | ||
1834 | otg_dbg("error state before suspend\n "); | ||
1835 | break; | ||
1836 | } | ||
1837 | spin_unlock(&langwell->wq_lock); | ||
1838 | |||
1839 | return ret; | ||
1840 | } | ||
1841 | |||
1842 | static void transceiver_resume(struct pci_dev *pdev) | ||
1843 | { | ||
1844 | pci_restore_state(pdev); | ||
1845 | pci_set_power_state(pdev, PCI_D0); | ||
1846 | langwell_otg_phy_low_power(0); | ||
1847 | } | ||
1848 | |||
1849 | static int langwell_otg_resume(struct pci_dev *pdev) | ||
1850 | { | ||
1851 | int ret = 0; | ||
1852 | struct langwell_otg *langwell; | ||
1853 | |||
1854 | langwell = the_transceiver; | ||
1855 | |||
1856 | spin_lock(&langwell->wq_lock); | ||
1857 | |||
1858 | switch (langwell->otg.state) { | ||
1859 | case OTG_STATE_A_IDLE: | ||
1860 | case OTG_STATE_B_IDLE: | ||
1861 | case OTG_STATE_A_WAIT_VFALL: | ||
1862 | case OTG_STATE_A_VBUS_ERR: | ||
1863 | transceiver_resume(pdev); | ||
1864 | break; | ||
1865 | case OTG_STATE_A_WAIT_BCON: | ||
1866 | langwell_otg_add_timer(a_wait_bcon_tmr); | ||
1867 | langwell_otg_drv_vbus(1); | ||
1868 | if (langwell->host_ops) | ||
1869 | ret = langwell->host_ops->resume(pdev); | ||
1870 | break; | ||
1871 | case OTG_STATE_A_HOST: | ||
1872 | langwell_otg_drv_vbus(1); | ||
1873 | langwell_otg_phy_low_power(0); | ||
1874 | if (langwell->host_ops) | ||
1875 | ret = langwell->host_ops->resume(pdev); | ||
1876 | break; | ||
1877 | case OTG_STATE_B_PERIPHERAL: | ||
1878 | if (langwell->client_ops) | ||
1879 | ret = langwell->client_ops->resume(pdev); | ||
1880 | else | ||
1881 | otg_dbg("client driver not loaded.\n"); | ||
1882 | break; | ||
1883 | default: | ||
1884 | otg_dbg("error state before suspend\n "); | ||
1885 | break; | ||
1886 | } | ||
1887 | |||
1888 | if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, | ||
1889 | driver_name, the_transceiver) != 0) { | ||
1890 | otg_dbg("request interrupt %d failed\n", pdev->irq); | ||
1891 | ret = -EBUSY; | ||
1892 | } | ||
1893 | |||
1894 | /* enable OTG interrupts */ | ||
1895 | langwell_otg_intr(1); | ||
1896 | |||
1897 | spin_unlock(&langwell->wq_lock); | ||
1898 | |||
1899 | queue_work(langwell->qwork, &langwell->work); | ||
1900 | |||
1901 | |||
1902 | return ret; | ||
1903 | } | ||
1904 | |||
1905 | static int __init langwell_otg_init(void) | ||
1906 | { | ||
1907 | return pci_register_driver(&otg_pci_driver); | ||
1908 | } | ||
1909 | module_init(langwell_otg_init); | ||
1910 | |||
1911 | static void __exit langwell_otg_cleanup(void) | ||
1912 | { | ||
1913 | pci_unregister_driver(&otg_pci_driver); | ||
1914 | } | ||
1915 | module_exit(langwell_otg_cleanup); | ||
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index 9ed5ea568679..af456b48985f 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c | |||
@@ -53,6 +53,7 @@ EXPORT_SYMBOL(usb_nop_xceiv_register); | |||
53 | void usb_nop_xceiv_unregister(void) | 53 | void usb_nop_xceiv_unregister(void) |
54 | { | 54 | { |
55 | platform_device_unregister(pd); | 55 | platform_device_unregister(pd); |
56 | pd = NULL; | ||
56 | } | 57 | } |
57 | EXPORT_SYMBOL(usb_nop_xceiv_unregister); | 58 | EXPORT_SYMBOL(usb_nop_xceiv_unregister); |
58 | 59 | ||
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 247b61bfb7f4..0e4f2e41ace5 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
@@ -169,9 +169,11 @@ static int usb_console_setup(struct console *co, char *options) | |||
169 | kfree(tty); | 169 | kfree(tty); |
170 | } | 170 | } |
171 | } | 171 | } |
172 | /* So we know not to kill the hardware on a hangup on this | 172 | /* Now that any required fake tty operations are completed restore |
173 | port. We have also bumped the use count by one so it won't go | 173 | * the tty port count */ |
174 | idle */ | 174 | --port->port.count; |
175 | /* The console is special in terms of closing the device so | ||
176 | * indicate this port is now acting as a system console. */ | ||
175 | port->console = 1; | 177 | port->console = 1; |
176 | retval = 0; | 178 | retval = 0; |
177 | 179 | ||
@@ -204,7 +206,7 @@ static void usb_console_write(struct console *co, | |||
204 | 206 | ||
205 | dbg("%s - port %d, %d byte(s)", __func__, port->number, count); | 207 | dbg("%s - port %d, %d byte(s)", __func__, port->number, count); |
206 | 208 | ||
207 | if (!port->port.count) { | 209 | if (!port->console) { |
208 | dbg("%s - port not opened", __func__); | 210 | dbg("%s - port not opened", __func__); |
209 | return; | 211 | return; |
210 | } | 212 | } |
@@ -300,8 +302,7 @@ void usb_serial_console_exit(void) | |||
300 | { | 302 | { |
301 | if (usbcons_info.port) { | 303 | if (usbcons_info.port) { |
302 | unregister_console(&usbcons); | 304 | unregister_console(&usbcons); |
303 | if (usbcons_info.port->port.count) | 305 | usbcons_info.port->console = 0; |
304 | usbcons_info.port->port.count--; | ||
305 | usbcons_info.port = NULL; | 306 | usbcons_info.port = NULL; |
306 | } | 307 | } |
307 | } | 308 | } |
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2b9eeda62bfe..e9a40b820fd4 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c | |||
@@ -67,6 +67,8 @@ static struct usb_device_id id_table [] = { | |||
67 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ | 67 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ |
68 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ | 68 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ |
69 | { USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */ | 69 | { USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */ |
70 | { USB_DEVICE(0x10C4, 0x1101) }, /* Arkham Technology DS101 Bus Monitor */ | ||
71 | { USB_DEVICE(0x10C4, 0x1601) }, /* Arkham Technology DS101 Adapter */ | ||
70 | { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ | 72 | { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ |
71 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ | 73 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ |
72 | { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ | 74 | { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ |
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 9734085fd2fe..59adfe123110 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -1228,8 +1228,8 @@ static void cypress_read_int_callback(struct urb *urb) | |||
1228 | /* precursor to disconnect so just go away */ | 1228 | /* precursor to disconnect so just go away */ |
1229 | return; | 1229 | return; |
1230 | case -EPIPE: | 1230 | case -EPIPE: |
1231 | usb_clear_halt(port->serial->dev, 0x81); | 1231 | /* Can't call usb_clear_halt while in_interrupt */ |
1232 | break; | 1232 | /* FALLS THROUGH */ |
1233 | default: | 1233 | default: |
1234 | /* something ugly is going on... */ | 1234 | /* something ugly is going on... */ |
1235 | dev_err(&urb->dev->dev, | 1235 | dev_err(&urb->dev->dev, |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 5a8ae274d258..60c64cc5be2a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -108,6 +108,7 @@ struct ftdi_sio_quirk { | |||
108 | 108 | ||
109 | static int ftdi_jtag_probe(struct usb_serial *serial); | 109 | static int ftdi_jtag_probe(struct usb_serial *serial); |
110 | static int ftdi_mtxorb_hack_setup(struct usb_serial *serial); | 110 | static int ftdi_mtxorb_hack_setup(struct usb_serial *serial); |
111 | static int ftdi_NDI_device_setup(struct usb_serial *serial); | ||
111 | static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); | 112 | static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); |
112 | static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); | 113 | static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); |
113 | 114 | ||
@@ -119,6 +120,10 @@ static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = { | |||
119 | .probe = ftdi_mtxorb_hack_setup, | 120 | .probe = ftdi_mtxorb_hack_setup, |
120 | }; | 121 | }; |
121 | 122 | ||
123 | static struct ftdi_sio_quirk ftdi_NDI_device_quirk = { | ||
124 | .probe = ftdi_NDI_device_setup, | ||
125 | }; | ||
126 | |||
122 | static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { | 127 | static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { |
123 | .port_probe = ftdi_USB_UIRT_setup, | 128 | .port_probe = ftdi_USB_UIRT_setup, |
124 | }; | 129 | }; |
@@ -192,6 +197,7 @@ static struct usb_device_id id_table_combined [] = { | |||
192 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) }, | 197 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) }, |
193 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, | 198 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, |
194 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, | 199 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, |
200 | { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) }, | ||
195 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, | 201 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, |
196 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, | 202 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, |
197 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, | 203 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, |
@@ -580,6 +586,9 @@ static struct usb_device_id id_table_combined [] = { | |||
580 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, | 586 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, |
581 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, | 587 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, |
582 | { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) }, | 588 | { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) }, |
589 | { USB_DEVICE(FTDI_VID, FTDI_CCSLOAD_N_GO_3_PID) }, | ||
590 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU64_4_PID) }, | ||
591 | { USB_DEVICE(FTDI_VID, FTDI_CCSPRIME8_5_PID) }, | ||
583 | { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, | 592 | { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, |
584 | { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, | 593 | { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, |
585 | { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, | 594 | { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, |
@@ -645,6 +654,16 @@ static struct usb_device_id id_table_combined [] = { | |||
645 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, | 654 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, |
646 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, | 655 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, |
647 | { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, | 656 | { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, |
657 | { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID), | ||
658 | .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, | ||
659 | { USB_DEVICE(FTDI_VID, FTDI_NDI_SPECTRA_SCU_PID), | ||
660 | .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, | ||
661 | { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_2_PID), | ||
662 | .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, | ||
663 | { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_3_PID), | ||
664 | .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, | ||
665 | { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), | ||
666 | .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, | ||
648 | { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, | 667 | { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, |
649 | { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, | 668 | { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, |
650 | { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, | 669 | { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, |
@@ -661,6 +680,8 @@ static struct usb_device_id id_table_combined [] = { | |||
661 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 680 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
662 | { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID), | 681 | { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID), |
663 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 682 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
683 | { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID), | ||
684 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | ||
664 | { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, | 685 | { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, |
665 | { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, | 686 | { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, |
666 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, | 687 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, |
@@ -668,7 +689,6 @@ static struct usb_device_id id_table_combined [] = { | |||
668 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, | 689 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, |
669 | { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, | 690 | { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, |
670 | { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, | 691 | { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, |
671 | { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) }, | ||
672 | { USB_DEVICE(ATMEL_VID, STK541_PID) }, | 692 | { USB_DEVICE(ATMEL_VID, STK541_PID) }, |
673 | { USB_DEVICE(DE_VID, STB_PID) }, | 693 | { USB_DEVICE(DE_VID, STB_PID) }, |
674 | { USB_DEVICE(DE_VID, WHT_PID) }, | 694 | { USB_DEVICE(DE_VID, WHT_PID) }, |
@@ -1024,6 +1044,16 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, | |||
1024 | case FT2232C: /* FT2232C chip */ | 1044 | case FT2232C: /* FT2232C chip */ |
1025 | case FT232RL: | 1045 | case FT232RL: |
1026 | if (baud <= 3000000) { | 1046 | if (baud <= 3000000) { |
1047 | __u16 product_id = le16_to_cpu( | ||
1048 | port->serial->dev->descriptor.idProduct); | ||
1049 | if (((FTDI_NDI_HUC_PID == product_id) || | ||
1050 | (FTDI_NDI_SPECTRA_SCU_PID == product_id) || | ||
1051 | (FTDI_NDI_FUTURE_2_PID == product_id) || | ||
1052 | (FTDI_NDI_FUTURE_3_PID == product_id) || | ||
1053 | (FTDI_NDI_AURORA_SCU_PID == product_id)) && | ||
1054 | (baud == 19200)) { | ||
1055 | baud = 1200000; | ||
1056 | } | ||
1027 | div_value = ftdi_232bm_baud_to_divisor(baud); | 1057 | div_value = ftdi_232bm_baud_to_divisor(baud); |
1028 | } else { | 1058 | } else { |
1029 | dbg("%s - Baud rate too high!", __func__); | 1059 | dbg("%s - Baud rate too high!", __func__); |
@@ -1555,6 +1585,39 @@ static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv) | |||
1555 | } /* ftdi_HE_TIRA1_setup */ | 1585 | } /* ftdi_HE_TIRA1_setup */ |
1556 | 1586 | ||
1557 | /* | 1587 | /* |
1588 | * Module parameter to control latency timer for NDI FTDI-based USB devices. | ||
1589 | * If this value is not set in modprobe.conf.local its value will be set to 1ms. | ||
1590 | */ | ||
1591 | static int ndi_latency_timer = 1; | ||
1592 | |||
1593 | /* Setup for the NDI FTDI-based USB devices, which requires hardwired | ||
1594 | * baudrate (19200 gets mapped to 1200000). | ||
1595 | * | ||
1596 | * Called from usbserial:serial_probe. | ||
1597 | */ | ||
1598 | static int ftdi_NDI_device_setup(struct usb_serial *serial) | ||
1599 | { | ||
1600 | struct usb_device *udev = serial->dev; | ||
1601 | int latency = ndi_latency_timer; | ||
1602 | int rv = 0; | ||
1603 | char buf[1]; | ||
1604 | |||
1605 | if (latency == 0) | ||
1606 | latency = 1; | ||
1607 | if (latency > 99) | ||
1608 | latency = 99; | ||
1609 | |||
1610 | dbg("%s setting NDI device latency to %d", __func__, latency); | ||
1611 | dev_info(&udev->dev, "NDI device with a latency value of %d", latency); | ||
1612 | |||
1613 | rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
1614 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST, | ||
1615 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, | ||
1616 | latency, 0, buf, 0, WDR_TIMEOUT); | ||
1617 | return 0; | ||
1618 | } | ||
1619 | |||
1620 | /* | ||
1558 | * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko | 1621 | * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko |
1559 | * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from | 1622 | * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from |
1560 | * userspace using openocd. | 1623 | * userspace using openocd. |
@@ -2623,3 +2686,5 @@ MODULE_PARM_DESC(vendor, "User specified vendor ID (default=" | |||
2623 | module_param(product, ushort, 0); | 2686 | module_param(product, ushort, 0); |
2624 | MODULE_PARM_DESC(product, "User specified product ID"); | 2687 | MODULE_PARM_DESC(product, "User specified product ID"); |
2625 | 2688 | ||
2689 | module_param(ndi_latency_timer, int, S_IRUGO | S_IWUSR); | ||
2690 | MODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override"); | ||
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index f1d440a728a3..c9fbd7415092 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h | |||
@@ -506,6 +506,7 @@ | |||
506 | * | 506 | * |
507 | * Armin Laeuger originally sent the PID for the UM 100 module. | 507 | * Armin Laeuger originally sent the PID for the UM 100 module. |
508 | */ | 508 | */ |
509 | #define FTDI_R2000KU_TRUE_RNG 0xFB80 /* R2000KU TRUE RNG */ | ||
509 | #define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */ | 510 | #define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */ |
510 | #define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */ | 511 | #define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */ |
511 | #define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */ | 512 | #define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */ |
@@ -614,6 +615,9 @@ | |||
614 | #define FTDI_CCSICDU20_0_PID 0xF9D0 | 615 | #define FTDI_CCSICDU20_0_PID 0xF9D0 |
615 | #define FTDI_CCSICDU40_1_PID 0xF9D1 | 616 | #define FTDI_CCSICDU40_1_PID 0xF9D1 |
616 | #define FTDI_CCSMACHX_2_PID 0xF9D2 | 617 | #define FTDI_CCSMACHX_2_PID 0xF9D2 |
618 | #define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3 | ||
619 | #define FTDI_CCSICDU64_4_PID 0xF9D4 | ||
620 | #define FTDI_CCSPRIME8_5_PID 0xF9D5 | ||
617 | 621 | ||
618 | /* Inside Accesso contactless reader (http://www.insidefr.com) */ | 622 | /* Inside Accesso contactless reader (http://www.insidefr.com) */ |
619 | #define INSIDE_ACCESSO 0xFAD0 | 623 | #define INSIDE_ACCESSO 0xFAD0 |
@@ -736,6 +740,15 @@ | |||
736 | #define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ | 740 | #define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ |
737 | 741 | ||
738 | /* | 742 | /* |
743 | * NDI (www.ndigital.com) product ids | ||
744 | */ | ||
745 | #define FTDI_NDI_HUC_PID 0xDA70 /* NDI Host USB Converter */ | ||
746 | #define FTDI_NDI_SPECTRA_SCU_PID 0xDA71 /* NDI Spectra SCU */ | ||
747 | #define FTDI_NDI_FUTURE_2_PID 0xDA72 /* NDI future device #2 */ | ||
748 | #define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ | ||
749 | #define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ | ||
750 | |||
751 | /* | ||
739 | * Posiflex inc retail equipment (http://www.posiflex.com.tw) | 752 | * Posiflex inc retail equipment (http://www.posiflex.com.tw) |
740 | */ | 753 | */ |
741 | #define POSIFLEX_VID 0x0d3a /* Vendor ID */ | 754 | #define POSIFLEX_VID 0x0d3a /* Vendor ID */ |
@@ -848,9 +861,6 @@ | |||
848 | #define TML_VID 0x1B91 /* Vendor ID */ | 861 | #define TML_VID 0x1B91 /* Vendor ID */ |
849 | #define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */ | 862 | #define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */ |
850 | 863 | ||
851 | /* NDI Polaris System */ | ||
852 | #define FTDI_NDI_HUC_PID 0xDA70 | ||
853 | |||
854 | /* Propox devices */ | 864 | /* Propox devices */ |
855 | #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 | 865 | #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 |
856 | 866 | ||
@@ -934,6 +944,8 @@ | |||
934 | #define MARVELL_VID 0x9e88 | 944 | #define MARVELL_VID 0x9e88 |
935 | #define MARVELL_SHEEVAPLUG_PID 0x9e8f | 945 | #define MARVELL_SHEEVAPLUG_PID 0x9e8f |
936 | 946 | ||
947 | #define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */ | ||
948 | |||
937 | /* | 949 | /* |
938 | * BmRequestType: 1100 0000b | 950 | * BmRequestType: 1100 0000b |
939 | * bRequest: FTDI_E2_READ | 951 | * bRequest: FTDI_E2_READ |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 575816e6ba37..98262dd552bb 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -206,6 +206,7 @@ static int option_resume(struct usb_serial *serial); | |||
206 | #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 | 206 | #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 |
207 | #define NOVATELWIRELESS_PRODUCT_U727 0x5010 | 207 | #define NOVATELWIRELESS_PRODUCT_U727 0x5010 |
208 | #define NOVATELWIRELESS_PRODUCT_MC760 0x6000 | 208 | #define NOVATELWIRELESS_PRODUCT_MC760 0x6000 |
209 | #define NOVATELWIRELESS_PRODUCT_OVMC760 0x6002 | ||
209 | 210 | ||
210 | /* FUTURE NOVATEL PRODUCTS */ | 211 | /* FUTURE NOVATEL PRODUCTS */ |
211 | #define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0X6001 | 212 | #define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0X6001 |
@@ -307,11 +308,20 @@ static int option_resume(struct usb_serial *serial); | |||
307 | #define DLINK_VENDOR_ID 0x1186 | 308 | #define DLINK_VENDOR_ID 0x1186 |
308 | #define DLINK_PRODUCT_DWM_652 0x3e04 | 309 | #define DLINK_PRODUCT_DWM_652 0x3e04 |
309 | 310 | ||
311 | #define QISDA_VENDOR_ID 0x1da5 | ||
312 | #define QISDA_PRODUCT_H21_4512 0x4512 | ||
313 | #define QISDA_PRODUCT_H21_4523 0x4523 | ||
314 | #define QISDA_PRODUCT_H20_4515 0x4515 | ||
315 | #define QISDA_PRODUCT_H20_4519 0x4519 | ||
316 | |||
310 | 317 | ||
311 | /* TOSHIBA PRODUCTS */ | 318 | /* TOSHIBA PRODUCTS */ |
312 | #define TOSHIBA_VENDOR_ID 0x0930 | 319 | #define TOSHIBA_VENDOR_ID 0x0930 |
313 | #define TOSHIBA_PRODUCT_HSDPA_MINICARD 0x1302 | 320 | #define TOSHIBA_PRODUCT_HSDPA_MINICARD 0x1302 |
314 | 321 | ||
322 | #define ALINK_VENDOR_ID 0x1e0e | ||
323 | #define ALINK_PRODUCT_3GU 0x9200 | ||
324 | |||
315 | static struct usb_device_id option_ids[] = { | 325 | static struct usb_device_id option_ids[] = { |
316 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, | 326 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, |
317 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, | 327 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, |
@@ -430,6 +440,7 @@ static struct usb_device_id option_ids[] = { | |||
430 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ | 440 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ |
431 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */ | 441 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */ |
432 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */ | 442 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */ |
443 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, /* Novatel Ovation MC760 */ | ||
433 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */ | 444 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */ |
434 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */ | 445 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */ |
435 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */ | 446 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */ |
@@ -529,8 +540,13 @@ static struct usb_device_id option_ids[] = { | |||
529 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, | 540 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, |
530 | { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, | 541 | { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, |
531 | { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, | 542 | { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, |
532 | { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */ | 543 | { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) }, |
544 | { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) }, | ||
545 | { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) }, | ||
546 | { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) }, | ||
533 | { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ | 547 | { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ |
548 | { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, | ||
549 | { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, | ||
534 | { } /* Terminating entry */ | 550 | { } /* Terminating entry */ |
535 | }; | 551 | }; |
536 | MODULE_DEVICE_TABLE(usb, option_ids); | 552 | MODULE_DEVICE_TABLE(usb, option_ids); |
@@ -732,7 +748,6 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
732 | memcpy(this_urb->transfer_buffer, buf, todo); | 748 | memcpy(this_urb->transfer_buffer, buf, todo); |
733 | this_urb->transfer_buffer_length = todo; | 749 | this_urb->transfer_buffer_length = todo; |
734 | 750 | ||
735 | this_urb->dev = port->serial->dev; | ||
736 | err = usb_submit_urb(this_urb, GFP_ATOMIC); | 751 | err = usb_submit_urb(this_urb, GFP_ATOMIC); |
737 | if (err) { | 752 | if (err) { |
738 | dbg("usb_submit_urb %p (write bulk) failed " | 753 | dbg("usb_submit_urb %p (write bulk) failed " |
@@ -860,7 +875,6 @@ static void option_instat_callback(struct urb *urb) | |||
860 | 875 | ||
861 | /* Resubmit urb so we continue receiving IRQ data */ | 876 | /* Resubmit urb so we continue receiving IRQ data */ |
862 | if (status != -ESHUTDOWN && status != -ENOENT) { | 877 | if (status != -ESHUTDOWN && status != -ENOENT) { |
863 | urb->dev = serial->dev; | ||
864 | err = usb_submit_urb(urb, GFP_ATOMIC); | 878 | err = usb_submit_urb(urb, GFP_ATOMIC); |
865 | if (err) | 879 | if (err) |
866 | dbg("%s: resubmit intr urb failed. (%d)", | 880 | dbg("%s: resubmit intr urb failed. (%d)", |
@@ -921,23 +935,11 @@ static int option_open(struct tty_struct *tty, | |||
921 | 935 | ||
922 | dbg("%s", __func__); | 936 | dbg("%s", __func__); |
923 | 937 | ||
924 | /* Reset low level data toggle and start reading from endpoints */ | 938 | /* Start reading from the IN endpoint */ |
925 | for (i = 0; i < N_IN_URB; i++) { | 939 | for (i = 0; i < N_IN_URB; i++) { |
926 | urb = portdata->in_urbs[i]; | 940 | urb = portdata->in_urbs[i]; |
927 | if (!urb) | 941 | if (!urb) |
928 | continue; | 942 | continue; |
929 | if (urb->dev != serial->dev) { | ||
930 | dbg("%s: dev %p != %p", __func__, | ||
931 | urb->dev, serial->dev); | ||
932 | continue; | ||
933 | } | ||
934 | |||
935 | /* | ||
936 | * make sure endpoint data toggle is synchronized with the | ||
937 | * device | ||
938 | */ | ||
939 | usb_clear_halt(urb->dev, urb->pipe); | ||
940 | |||
941 | err = usb_submit_urb(urb, GFP_KERNEL); | 943 | err = usb_submit_urb(urb, GFP_KERNEL); |
942 | if (err) { | 944 | if (err) { |
943 | dbg("%s: submit urb %d failed (%d) %d", | 945 | dbg("%s: submit urb %d failed (%d) %d", |
@@ -946,16 +948,6 @@ static int option_open(struct tty_struct *tty, | |||
946 | } | 948 | } |
947 | } | 949 | } |
948 | 950 | ||
949 | /* Reset low level data toggle on out endpoints */ | ||
950 | for (i = 0; i < N_OUT_URB; i++) { | ||
951 | urb = portdata->out_urbs[i]; | ||
952 | if (!urb) | ||
953 | continue; | ||
954 | urb->dev = serial->dev; | ||
955 | /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
956 | usb_pipeout(urb->pipe), 0); */ | ||
957 | } | ||
958 | |||
959 | option_send_setup(port); | 951 | option_send_setup(port); |
960 | 952 | ||
961 | return 0; | 953 | return 0; |
@@ -1218,7 +1210,6 @@ static int option_resume(struct usb_serial *serial) | |||
1218 | dbg("%s: No interrupt URB for port %d\n", __func__, i); | 1210 | dbg("%s: No interrupt URB for port %d\n", __func__, i); |
1219 | continue; | 1211 | continue; |
1220 | } | 1212 | } |
1221 | port->interrupt_in_urb->dev = serial->dev; | ||
1222 | err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); | 1213 | err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); |
1223 | dbg("Submitted interrupt URB for port %d (result %d)", i, err); | 1214 | dbg("Submitted interrupt URB for port %d (result %d)", i, err); |
1224 | if (err < 0) { | 1215 | if (err < 0) { |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index efaf59c4f5d0..7d15bfa7c2db 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -94,6 +94,7 @@ static struct usb_device_id id_table [] = { | |||
94 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, | 94 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, |
95 | { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, | 95 | { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, |
96 | { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, | 96 | { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, |
97 | { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, | ||
97 | { } /* Terminating entry */ | 98 | { } /* Terminating entry */ |
98 | }; | 99 | }; |
99 | 100 | ||
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 1d7a22e3a9fd..12aac7d2462d 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h | |||
@@ -122,3 +122,7 @@ | |||
122 | /* Hewlett-Packard LD220-HP POS Pole Display */ | 122 | /* Hewlett-Packard LD220-HP POS Pole Display */ |
123 | #define HP_VENDOR_ID 0x03f0 | 123 | #define HP_VENDOR_ID 0x03f0 |
124 | #define HP_LD220_PRODUCT_ID 0x3524 | 124 | #define HP_LD220_PRODUCT_ID 0x3524 |
125 | |||
126 | /* Cressi Edy (diving computer) PC interface */ | ||
127 | #define CRESSI_VENDOR_ID 0x04b8 | ||
128 | #define CRESSI_EDY_PRODUCT_ID 0x0521 | ||
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 032f7aeb40a4..f48d05e0acc1 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -181,35 +181,50 @@ static const struct sierra_iface_info direct_ip_interface_blacklist = { | |||
181 | }; | 181 | }; |
182 | 182 | ||
183 | static struct usb_device_id id_table [] = { | 183 | static struct usb_device_id id_table [] = { |
184 | { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ | ||
185 | { USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */ | ||
186 | { USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */ | ||
187 | |||
184 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ | 188 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ |
185 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ | 189 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ |
186 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ | 190 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ |
187 | { USB_DEVICE(0x03f0, 0x1b1d) }, /* HP ev2200 a.k.a MC5720 */ | ||
188 | { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ | 191 | { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ |
189 | { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */ | ||
190 | { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ | 192 | { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ |
193 | { USB_DEVICE(0x1199, 0x0022) }, /* Sierra Wireless EM5725 */ | ||
194 | { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */ | ||
195 | { USB_DEVICE(0x1199, 0x0224) }, /* Sierra Wireless MC5727 */ | ||
191 | { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ | 196 | { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ |
192 | { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ | 197 | { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ |
198 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ | ||
193 | { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */ | 199 | { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */ |
194 | /* Sierra Wireless C597 */ | 200 | /* Sierra Wireless C597 */ |
195 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, | 201 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, |
196 | /* Sierra Wireless Device */ | 202 | /* Sierra Wireless T598 */ |
197 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) }, | 203 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) }, |
198 | { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless Device */ | 204 | { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless T11 */ |
199 | { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless Device */ | 205 | { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless AC402 */ |
200 | { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless Device */ | 206 | { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless MC5728 */ |
207 | { USB_DEVICE(0x1199, 0x0029) }, /* Sierra Wireless Device */ | ||
201 | 208 | ||
202 | { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ | 209 | { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ |
203 | { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ | ||
204 | { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ | 210 | { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ |
211 | { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ | ||
212 | { USB_DEVICE(0x1199, 0x6805) }, /* Sierra Wireless MC8765 */ | ||
213 | { USB_DEVICE(0x1199, 0x6808) }, /* Sierra Wireless MC8755 */ | ||
214 | { USB_DEVICE(0x1199, 0x6809) }, /* Sierra Wireless MC8765 */ | ||
205 | { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ | 215 | { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ |
206 | { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Lenovo) */ | 216 | { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 */ |
207 | { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */ | 217 | { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */ |
208 | { USB_DEVICE(0x03f0, 0x1e1d) }, /* HP hs2300 a.k.a MC8775 */ | 218 | { USB_DEVICE(0x1199, 0x6816) }, /* Sierra Wireless MC8775 */ |
209 | { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ | 219 | { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ |
210 | { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */ | 220 | { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */ |
221 | { USB_DEVICE(0x1199, 0x6822) }, /* Sierra Wireless AirCard 875E */ | ||
211 | { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */ | 222 | { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */ |
212 | { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ | 223 | { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ |
224 | { USB_DEVICE(0x1199, 0x6834) }, /* Sierra Wireless MC8780 */ | ||
225 | { USB_DEVICE(0x1199, 0x6835) }, /* Sierra Wireless MC8781 */ | ||
226 | { USB_DEVICE(0x1199, 0x6838) }, /* Sierra Wireless MC8780 */ | ||
227 | { USB_DEVICE(0x1199, 0x6839) }, /* Sierra Wireless MC8781 */ | ||
213 | { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */ | 228 | { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */ |
214 | { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ | 229 | { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ |
215 | /* Sierra Wireless MC8790, MC8791, MC8792 Composite */ | 230 | /* Sierra Wireless MC8790, MC8791, MC8792 Composite */ |
@@ -227,16 +242,13 @@ static struct usb_device_id id_table [] = { | |||
227 | { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */ | 242 | { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */ |
228 | /* Sierra Wireless C885 */ | 243 | /* Sierra Wireless C885 */ |
229 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)}, | 244 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)}, |
230 | /* Sierra Wireless Device */ | 245 | /* Sierra Wireless C888, Air Card 501, USB 303, USB 304 */ |
231 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)}, | 246 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)}, |
232 | /* Sierra Wireless Device */ | 247 | /* Sierra Wireless C22/C33 */ |
233 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)}, | 248 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)}, |
234 | /* Sierra Wireless Device */ | 249 | /* Sierra Wireless HSPA Non-Composite Device */ |
235 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, | 250 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, |
236 | 251 | { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ | |
237 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ | ||
238 | { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ | ||
239 | |||
240 | { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ | 252 | { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ |
241 | .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist | 253 | .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist |
242 | }, | 254 | }, |
@@ -814,7 +826,7 @@ static int sierra_startup(struct usb_serial *serial) | |||
814 | return 0; | 826 | return 0; |
815 | } | 827 | } |
816 | 828 | ||
817 | static void sierra_disconnect(struct usb_serial *serial) | 829 | static void sierra_release(struct usb_serial *serial) |
818 | { | 830 | { |
819 | int i; | 831 | int i; |
820 | struct usb_serial_port *port; | 832 | struct usb_serial_port *port; |
@@ -830,7 +842,6 @@ static void sierra_disconnect(struct usb_serial *serial) | |||
830 | if (!portdata) | 842 | if (!portdata) |
831 | continue; | 843 | continue; |
832 | kfree(portdata); | 844 | kfree(portdata); |
833 | usb_set_serial_port_data(port, NULL); | ||
834 | } | 845 | } |
835 | } | 846 | } |
836 | 847 | ||
@@ -853,7 +864,7 @@ static struct usb_serial_driver sierra_device = { | |||
853 | .tiocmget = sierra_tiocmget, | 864 | .tiocmget = sierra_tiocmget, |
854 | .tiocmset = sierra_tiocmset, | 865 | .tiocmset = sierra_tiocmset, |
855 | .attach = sierra_startup, | 866 | .attach = sierra_startup, |
856 | .disconnect = sierra_disconnect, | 867 | .release = sierra_release, |
857 | .read_int_callback = sierra_instat_callback, | 868 | .read_int_callback = sierra_instat_callback, |
858 | }; | 869 | }; |
859 | 870 | ||
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 991d8232e376..14971a926990 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
@@ -191,7 +191,6 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = { | |||
191 | { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, | 191 | { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, |
192 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, | 192 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, |
193 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, | 193 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, |
194 | { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, | ||
195 | }; | 194 | }; |
196 | 195 | ||
197 | static struct usb_device_id ti_id_table_combined[14+2*TI_EXTRA_VID_PID_COUNT+1] = { | 196 | static struct usb_device_id ti_id_table_combined[14+2*TI_EXTRA_VID_PID_COUNT+1] = { |
@@ -1658,7 +1657,7 @@ static int ti_do_download(struct usb_device *dev, int pipe, | |||
1658 | u8 cs = 0; | 1657 | u8 cs = 0; |
1659 | int done; | 1658 | int done; |
1660 | struct ti_firmware_header *header; | 1659 | struct ti_firmware_header *header; |
1661 | int status; | 1660 | int status = 0; |
1662 | int len; | 1661 | int len; |
1663 | 1662 | ||
1664 | for (pos = sizeof(struct ti_firmware_header); pos < size; pos++) | 1663 | for (pos = sizeof(struct ti_firmware_header); pos < size; pos++) |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 0c39b55aeef4..bd7581b3a48a 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -221,7 +221,8 @@ static int serial_open (struct tty_struct *tty, struct file *filp) | |||
221 | tty->driver_data = port; | 221 | tty->driver_data = port; |
222 | tty_port_tty_set(&port->port, tty); | 222 | tty_port_tty_set(&port->port, tty); |
223 | 223 | ||
224 | if (port->port.count == 1) { | 224 | /* If the console is attached, the device is already open */ |
225 | if (port->port.count == 1 && !port->console) { | ||
225 | 226 | ||
226 | /* lock this module before we call it | 227 | /* lock this module before we call it |
227 | * this may fail, which means we must bail out, | 228 | * this may fail, which means we must bail out, |
diff --git a/drivers/usb/storage/option_ms.c b/drivers/usb/storage/option_ms.c index d41cc0a970f7..773a5cd38c5a 100644 --- a/drivers/usb/storage/option_ms.c +++ b/drivers/usb/storage/option_ms.c | |||
@@ -118,6 +118,9 @@ static int option_inquiry(struct us_data *us) | |||
118 | 118 | ||
119 | result = memcmp(buffer+8, "Option", 6); | 119 | result = memcmp(buffer+8, "Option", 6); |
120 | 120 | ||
121 | if (result != 0) | ||
122 | result = memcmp(buffer+8, "ZCOPTION", 8); | ||
123 | |||
121 | /* Read the CSW */ | 124 | /* Read the CSW */ |
122 | usb_stor_bulk_transfer_buf(us, | 125 | usb_stor_bulk_transfer_buf(us, |
123 | us->recv_bulk_pipe, | 126 | us->recv_bulk_pipe, |