diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-26 21:00:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-26 21:00:28 -0400 |
commit | bcba282ab399eec1c8b8dcb49c43a33813971913 (patch) | |
tree | de81927192d6b02071479aa08a78466878d115c1 | |
parent | fb740f9bab3b3c049d6207b148e45de05163b6e5 (diff) | |
parent | b4731977243c1ae9cfd8b3971ffc15425b7d7545 (diff) |
Merge tag 'usb-4.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH:
"Here are some USB driver fixes for 4.3-rc3.
There's the usual assortment of new device ids, combined with xhci and
gadget driver fixes. Full details in the shortlog. All of these have
been in linux-next with no reported problems"
* tag 'usb-4.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (34 commits)
MAINTAINERS: remove amd5536udc USB gadget driver maintainer
USB: whiteheat: fix potential null-deref at probe
xhci: init command timeout timer earlier to avoid deleting it uninitialized
xhci: change xhci 1.0 only restrictions to support xhci 1.1
usb: xhci: exit early in xhci_setup_device() if we're halted or dying
usb: xhci: stop everything on the first call to xhci_stop
usb: xhci: Clear XHCI_STATE_DYING on start
usb: xhci: lock mutex on xhci_stop
xhci: Move xhci_pme_quirk() behind #ifdef CONFIG_PM
xhci: give command abortion one more chance before killing xhci
usb: Use the USB_SS_MULT() macro to get the burst multiplier.
usb: dwc3: gadget: Fix BUG in RT config
usb: musb: fix cppi channel teardown for isoch transfer
usb: phy: isp1301: Export I2C module alias information
usb: gadget: drop null test before destroy functions
usb: gadget: dummy_hcd: in transfer(), return data sent, not limit
usb: gadget: dummy_hcd: fix rescan logic for transfer
usb: gadget: dummy_hcd: fix unneeded else-if condition
usb: gadget: dummy_hcd: emulate sending zlp in packet logic
usb: musb: dsps: fix polling in device-only mode
...
29 files changed, 288 insertions, 177 deletions
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt index d71ef07bca5d..a057b75ba4b5 100644 --- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt +++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt | |||
@@ -6,6 +6,7 @@ Required properties: | |||
6 | "lsi,zevio-usb" | 6 | "lsi,zevio-usb" |
7 | "qcom,ci-hdrc" | 7 | "qcom,ci-hdrc" |
8 | "chipidea,usb2" | 8 | "chipidea,usb2" |
9 | "xlnx,zynq-usb-2.20a" | ||
9 | - reg: base address and length of the registers | 10 | - reg: base address and length of the registers |
10 | - interrupts: interrupt for the USB controller | 11 | - interrupts: interrupt for the USB controller |
11 | 12 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index a3077df7e68a..9f6685f6c5a9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -615,9 +615,8 @@ F: Documentation/hwmon/fam15h_power | |||
615 | F: drivers/hwmon/fam15h_power.c | 615 | F: drivers/hwmon/fam15h_power.c |
616 | 616 | ||
617 | AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER | 617 | AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER |
618 | M: Thomas Dahlmann <dahlmann.thomas@arcor.de> | ||
619 | L: linux-geode@lists.infradead.org (moderated for non-subscribers) | 618 | L: linux-geode@lists.infradead.org (moderated for non-subscribers) |
620 | S: Supported | 619 | S: Orphan |
621 | F: drivers/usb/gadget/udc/amd5536udc.* | 620 | F: drivers/usb/gadget/udc/amd5536udc.* |
622 | 621 | ||
623 | AMD GEODE PROCESSOR/CHIPSET SUPPORT | 622 | AMD GEODE PROCESSOR/CHIPSET SUPPORT |
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 867e9f3f3859..dcc50c878159 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c | |||
@@ -61,7 +61,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = { | |||
61 | { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data}, | 61 | { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data}, |
62 | { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data}, | 62 | { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data}, |
63 | { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data}, | 63 | { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data}, |
64 | { .compatible = "fsl,imx6sx-usb", .data = &imx6sl_usb_data}, | 64 | { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data}, |
65 | { /* sentinel */ } | 65 | { /* sentinel */ } |
66 | }; | 66 | }; |
67 | MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); | 67 | MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); |
diff --git a/drivers/usb/chipidea/ci_hdrc_usb2.c b/drivers/usb/chipidea/ci_hdrc_usb2.c index 9eae1a16cef9..4456d2cf80ff 100644 --- a/drivers/usb/chipidea/ci_hdrc_usb2.c +++ b/drivers/usb/chipidea/ci_hdrc_usb2.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/dma-mapping.h> | 12 | #include <linux/dma-mapping.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/of.h> | 14 | #include <linux/of.h> |
15 | #include <linux/of_platform.h> | ||
15 | #include <linux/phy/phy.h> | 16 | #include <linux/phy/phy.h> |
16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
17 | #include <linux/usb/chipidea.h> | 18 | #include <linux/usb/chipidea.h> |
@@ -30,18 +31,36 @@ static const struct ci_hdrc_platform_data ci_default_pdata = { | |||
30 | .flags = CI_HDRC_DISABLE_STREAMING, | 31 | .flags = CI_HDRC_DISABLE_STREAMING, |
31 | }; | 32 | }; |
32 | 33 | ||
34 | static struct ci_hdrc_platform_data ci_zynq_pdata = { | ||
35 | .capoffset = DEF_CAPOFFSET, | ||
36 | }; | ||
37 | |||
38 | static const struct of_device_id ci_hdrc_usb2_of_match[] = { | ||
39 | { .compatible = "chipidea,usb2"}, | ||
40 | { .compatible = "xlnx,zynq-usb-2.20a", .data = &ci_zynq_pdata}, | ||
41 | { } | ||
42 | }; | ||
43 | MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match); | ||
44 | |||
33 | static int ci_hdrc_usb2_probe(struct platform_device *pdev) | 45 | static int ci_hdrc_usb2_probe(struct platform_device *pdev) |
34 | { | 46 | { |
35 | struct device *dev = &pdev->dev; | 47 | struct device *dev = &pdev->dev; |
36 | struct ci_hdrc_usb2_priv *priv; | 48 | struct ci_hdrc_usb2_priv *priv; |
37 | struct ci_hdrc_platform_data *ci_pdata = dev_get_platdata(dev); | 49 | struct ci_hdrc_platform_data *ci_pdata = dev_get_platdata(dev); |
38 | int ret; | 50 | int ret; |
51 | const struct of_device_id *match; | ||
39 | 52 | ||
40 | if (!ci_pdata) { | 53 | if (!ci_pdata) { |
41 | ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL); | 54 | ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL); |
42 | *ci_pdata = ci_default_pdata; /* struct copy */ | 55 | *ci_pdata = ci_default_pdata; /* struct copy */ |
43 | } | 56 | } |
44 | 57 | ||
58 | match = of_match_device(ci_hdrc_usb2_of_match, &pdev->dev); | ||
59 | if (match && match->data) { | ||
60 | /* struct copy */ | ||
61 | *ci_pdata = *(struct ci_hdrc_platform_data *)match->data; | ||
62 | } | ||
63 | |||
45 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 64 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
46 | if (!priv) | 65 | if (!priv) |
47 | return -ENOMEM; | 66 | return -ENOMEM; |
@@ -96,12 +115,6 @@ static int ci_hdrc_usb2_remove(struct platform_device *pdev) | |||
96 | return 0; | 115 | return 0; |
97 | } | 116 | } |
98 | 117 | ||
99 | static const struct of_device_id ci_hdrc_usb2_of_match[] = { | ||
100 | { .compatible = "chipidea,usb2" }, | ||
101 | { } | ||
102 | }; | ||
103 | MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match); | ||
104 | |||
105 | static struct platform_driver ci_hdrc_usb2_driver = { | 118 | static struct platform_driver ci_hdrc_usb2_driver = { |
106 | .probe = ci_hdrc_usb2_probe, | 119 | .probe = ci_hdrc_usb2_probe, |
107 | .remove = ci_hdrc_usb2_remove, | 120 | .remove = ci_hdrc_usb2_remove, |
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index a637da25dda0..8223fe73ea85 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c | |||
@@ -656,6 +656,44 @@ __acquires(hwep->lock) | |||
656 | return 0; | 656 | return 0; |
657 | } | 657 | } |
658 | 658 | ||
659 | static int _ep_set_halt(struct usb_ep *ep, int value, bool check_transfer) | ||
660 | { | ||
661 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); | ||
662 | int direction, retval = 0; | ||
663 | unsigned long flags; | ||
664 | |||
665 | if (ep == NULL || hwep->ep.desc == NULL) | ||
666 | return -EINVAL; | ||
667 | |||
668 | if (usb_endpoint_xfer_isoc(hwep->ep.desc)) | ||
669 | return -EOPNOTSUPP; | ||
670 | |||
671 | spin_lock_irqsave(hwep->lock, flags); | ||
672 | |||
673 | if (value && hwep->dir == TX && check_transfer && | ||
674 | !list_empty(&hwep->qh.queue) && | ||
675 | !usb_endpoint_xfer_control(hwep->ep.desc)) { | ||
676 | spin_unlock_irqrestore(hwep->lock, flags); | ||
677 | return -EAGAIN; | ||
678 | } | ||
679 | |||
680 | direction = hwep->dir; | ||
681 | do { | ||
682 | retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value); | ||
683 | |||
684 | if (!value) | ||
685 | hwep->wedge = 0; | ||
686 | |||
687 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) | ||
688 | hwep->dir = (hwep->dir == TX) ? RX : TX; | ||
689 | |||
690 | } while (hwep->dir != direction); | ||
691 | |||
692 | spin_unlock_irqrestore(hwep->lock, flags); | ||
693 | return retval; | ||
694 | } | ||
695 | |||
696 | |||
659 | /** | 697 | /** |
660 | * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts | 698 | * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts |
661 | * @gadget: gadget | 699 | * @gadget: gadget |
@@ -1051,7 +1089,7 @@ __acquires(ci->lock) | |||
1051 | num += ci->hw_ep_max / 2; | 1089 | num += ci->hw_ep_max / 2; |
1052 | 1090 | ||
1053 | spin_unlock(&ci->lock); | 1091 | spin_unlock(&ci->lock); |
1054 | err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep); | 1092 | err = _ep_set_halt(&ci->ci_hw_ep[num].ep, 1, false); |
1055 | spin_lock(&ci->lock); | 1093 | spin_lock(&ci->lock); |
1056 | if (!err) | 1094 | if (!err) |
1057 | isr_setup_status_phase(ci); | 1095 | isr_setup_status_phase(ci); |
@@ -1117,8 +1155,8 @@ delegate: | |||
1117 | 1155 | ||
1118 | if (err < 0) { | 1156 | if (err < 0) { |
1119 | spin_unlock(&ci->lock); | 1157 | spin_unlock(&ci->lock); |
1120 | if (usb_ep_set_halt(&hwep->ep)) | 1158 | if (_ep_set_halt(&hwep->ep, 1, false)) |
1121 | dev_err(ci->dev, "error: ep_set_halt\n"); | 1159 | dev_err(ci->dev, "error: _ep_set_halt\n"); |
1122 | spin_lock(&ci->lock); | 1160 | spin_lock(&ci->lock); |
1123 | } | 1161 | } |
1124 | } | 1162 | } |
@@ -1149,9 +1187,9 @@ __acquires(ci->lock) | |||
1149 | err = isr_setup_status_phase(ci); | 1187 | err = isr_setup_status_phase(ci); |
1150 | if (err < 0) { | 1188 | if (err < 0) { |
1151 | spin_unlock(&ci->lock); | 1189 | spin_unlock(&ci->lock); |
1152 | if (usb_ep_set_halt(&hwep->ep)) | 1190 | if (_ep_set_halt(&hwep->ep, 1, false)) |
1153 | dev_err(ci->dev, | 1191 | dev_err(ci->dev, |
1154 | "error: ep_set_halt\n"); | 1192 | "error: _ep_set_halt\n"); |
1155 | spin_lock(&ci->lock); | 1193 | spin_lock(&ci->lock); |
1156 | } | 1194 | } |
1157 | } | 1195 | } |
@@ -1397,41 +1435,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) | |||
1397 | */ | 1435 | */ |
1398 | static int ep_set_halt(struct usb_ep *ep, int value) | 1436 | static int ep_set_halt(struct usb_ep *ep, int value) |
1399 | { | 1437 | { |
1400 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); | 1438 | return _ep_set_halt(ep, value, true); |
1401 | int direction, retval = 0; | ||
1402 | unsigned long flags; | ||
1403 | |||
1404 | if (ep == NULL || hwep->ep.desc == NULL) | ||
1405 | return -EINVAL; | ||
1406 | |||
1407 | if (usb_endpoint_xfer_isoc(hwep->ep.desc)) | ||
1408 | return -EOPNOTSUPP; | ||
1409 | |||
1410 | spin_lock_irqsave(hwep->lock, flags); | ||
1411 | |||
1412 | #ifndef STALL_IN | ||
1413 | /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */ | ||
1414 | if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX && | ||
1415 | !list_empty(&hwep->qh.queue)) { | ||
1416 | spin_unlock_irqrestore(hwep->lock, flags); | ||
1417 | return -EAGAIN; | ||
1418 | } | ||
1419 | #endif | ||
1420 | |||
1421 | direction = hwep->dir; | ||
1422 | do { | ||
1423 | retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value); | ||
1424 | |||
1425 | if (!value) | ||
1426 | hwep->wedge = 0; | ||
1427 | |||
1428 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) | ||
1429 | hwep->dir = (hwep->dir == TX) ? RX : TX; | ||
1430 | |||
1431 | } while (hwep->dir != direction); | ||
1432 | |||
1433 | spin_unlock_irqrestore(hwep->lock, flags); | ||
1434 | return retval; | ||
1435 | } | 1439 | } |
1436 | 1440 | ||
1437 | /** | 1441 | /** |
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index b2a540b43f97..b9ddf0c1ffe5 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c | |||
@@ -112,7 +112,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, | |||
112 | cfgno, inum, asnum, ep->desc.bEndpointAddress); | 112 | cfgno, inum, asnum, ep->desc.bEndpointAddress); |
113 | ep->ss_ep_comp.bmAttributes = 16; | 113 | ep->ss_ep_comp.bmAttributes = 16; |
114 | } else if (usb_endpoint_xfer_isoc(&ep->desc) && | 114 | } else if (usb_endpoint_xfer_isoc(&ep->desc) && |
115 | desc->bmAttributes > 2) { | 115 | USB_SS_MULT(desc->bmAttributes) > 3) { |
116 | dev_warn(ddev, "Isoc endpoint has Mult of %d in " | 116 | dev_warn(ddev, "Isoc endpoint has Mult of %d in " |
117 | "config %d interface %d altsetting %d ep %d: " | 117 | "config %d interface %d altsetting %d ep %d: " |
118 | "setting to 3\n", desc->bmAttributes + 1, | 118 | "setting to 3\n", desc->bmAttributes + 1, |
@@ -121,7 +121,8 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, | |||
121 | } | 121 | } |
122 | 122 | ||
123 | if (usb_endpoint_xfer_isoc(&ep->desc)) | 123 | if (usb_endpoint_xfer_isoc(&ep->desc)) |
124 | max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) * | 124 | max_tx = (desc->bMaxBurst + 1) * |
125 | (USB_SS_MULT(desc->bmAttributes)) * | ||
125 | usb_endpoint_maxp(&ep->desc); | 126 | usb_endpoint_maxp(&ep->desc); |
126 | else if (usb_endpoint_xfer_int(&ep->desc)) | 127 | else if (usb_endpoint_xfer_int(&ep->desc)) |
127 | max_tx = usb_endpoint_maxp(&ep->desc) * | 128 | max_tx = usb_endpoint_maxp(&ep->desc) * |
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index a5a1b7c45743..22e9606d8e08 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c | |||
@@ -514,8 +514,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
514 | goto err1; | 514 | goto err1; |
515 | } | 515 | } |
516 | 516 | ||
517 | dwc3_omap_enable_irqs(omap); | ||
518 | |||
519 | ret = dwc3_omap_extcon_register(omap); | 517 | ret = dwc3_omap_extcon_register(omap); |
520 | if (ret < 0) | 518 | if (ret < 0) |
521 | goto err2; | 519 | goto err2; |
@@ -526,6 +524,8 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
526 | goto err3; | 524 | goto err3; |
527 | } | 525 | } |
528 | 526 | ||
527 | dwc3_omap_enable_irqs(omap); | ||
528 | |||
529 | return 0; | 529 | return 0; |
530 | 530 | ||
531 | err3: | 531 | err3: |
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 0c25704dcb6b..1e8bdf817811 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -2665,8 +2665,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) | |||
2665 | int i; | 2665 | int i; |
2666 | irqreturn_t ret = IRQ_NONE; | 2666 | irqreturn_t ret = IRQ_NONE; |
2667 | 2667 | ||
2668 | spin_lock(&dwc->lock); | ||
2669 | |||
2670 | for (i = 0; i < dwc->num_event_buffers; i++) { | 2668 | for (i = 0; i < dwc->num_event_buffers; i++) { |
2671 | irqreturn_t status; | 2669 | irqreturn_t status; |
2672 | 2670 | ||
@@ -2675,8 +2673,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) | |||
2675 | ret = status; | 2673 | ret = status; |
2676 | } | 2674 | } |
2677 | 2675 | ||
2678 | spin_unlock(&dwc->lock); | ||
2679 | |||
2680 | return ret; | 2676 | return ret; |
2681 | } | 2677 | } |
2682 | 2678 | ||
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 978435a51038..6399c106a3a5 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c | |||
@@ -186,6 +186,7 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget) | |||
186 | 186 | ||
187 | list_for_each_entry (ep, &gadget->ep_list, ep_list) { | 187 | list_for_each_entry (ep, &gadget->ep_list, ep_list) { |
188 | ep->claimed = false; | 188 | ep->claimed = false; |
189 | ep->driver_data = NULL; | ||
189 | } | 190 | } |
190 | gadget->in_epnum = 0; | 191 | gadget->in_epnum = 0; |
191 | gadget->out_epnum = 0; | 192 | gadget->out_epnum = 0; |
diff --git a/drivers/usb/gadget/udc/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c index fdacddb18c00..175ca93fe5e2 100644 --- a/drivers/usb/gadget/udc/amd5536udc.c +++ b/drivers/usb/gadget/udc/amd5536udc.c | |||
@@ -3138,8 +3138,8 @@ static void udc_pci_remove(struct pci_dev *pdev) | |||
3138 | writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg); | 3138 | writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg); |
3139 | if (dev->irq_registered) | 3139 | if (dev->irq_registered) |
3140 | free_irq(pdev->irq, dev); | 3140 | free_irq(pdev->irq, dev); |
3141 | if (dev->regs) | 3141 | if (dev->virt_addr) |
3142 | iounmap(dev->regs); | 3142 | iounmap(dev->virt_addr); |
3143 | if (dev->mem_region) | 3143 | if (dev->mem_region) |
3144 | release_mem_region(pci_resource_start(pdev, 0), | 3144 | release_mem_region(pci_resource_start(pdev, 0), |
3145 | pci_resource_len(pdev, 0)); | 3145 | pci_resource_len(pdev, 0)); |
@@ -3226,17 +3226,13 @@ static int udc_pci_probe( | |||
3226 | 3226 | ||
3227 | /* init */ | 3227 | /* init */ |
3228 | dev = kzalloc(sizeof(struct udc), GFP_KERNEL); | 3228 | dev = kzalloc(sizeof(struct udc), GFP_KERNEL); |
3229 | if (!dev) { | 3229 | if (!dev) |
3230 | retval = -ENOMEM; | 3230 | return -ENOMEM; |
3231 | goto finished; | ||
3232 | } | ||
3233 | 3231 | ||
3234 | /* pci setup */ | 3232 | /* pci setup */ |
3235 | if (pci_enable_device(pdev) < 0) { | 3233 | if (pci_enable_device(pdev) < 0) { |
3236 | kfree(dev); | ||
3237 | dev = NULL; | ||
3238 | retval = -ENODEV; | 3234 | retval = -ENODEV; |
3239 | goto finished; | 3235 | goto err_pcidev; |
3240 | } | 3236 | } |
3241 | dev->active = 1; | 3237 | dev->active = 1; |
3242 | 3238 | ||
@@ -3246,28 +3242,22 @@ static int udc_pci_probe( | |||
3246 | 3242 | ||
3247 | if (!request_mem_region(resource, len, name)) { | 3243 | if (!request_mem_region(resource, len, name)) { |
3248 | dev_dbg(&pdev->dev, "pci device used already\n"); | 3244 | dev_dbg(&pdev->dev, "pci device used already\n"); |
3249 | kfree(dev); | ||
3250 | dev = NULL; | ||
3251 | retval = -EBUSY; | 3245 | retval = -EBUSY; |
3252 | goto finished; | 3246 | goto err_memreg; |
3253 | } | 3247 | } |
3254 | dev->mem_region = 1; | 3248 | dev->mem_region = 1; |
3255 | 3249 | ||
3256 | dev->virt_addr = ioremap_nocache(resource, len); | 3250 | dev->virt_addr = ioremap_nocache(resource, len); |
3257 | if (dev->virt_addr == NULL) { | 3251 | if (dev->virt_addr == NULL) { |
3258 | dev_dbg(&pdev->dev, "start address cannot be mapped\n"); | 3252 | dev_dbg(&pdev->dev, "start address cannot be mapped\n"); |
3259 | kfree(dev); | ||
3260 | dev = NULL; | ||
3261 | retval = -EFAULT; | 3253 | retval = -EFAULT; |
3262 | goto finished; | 3254 | goto err_ioremap; |
3263 | } | 3255 | } |
3264 | 3256 | ||
3265 | if (!pdev->irq) { | 3257 | if (!pdev->irq) { |
3266 | dev_err(&pdev->dev, "irq not set\n"); | 3258 | dev_err(&pdev->dev, "irq not set\n"); |
3267 | kfree(dev); | ||
3268 | dev = NULL; | ||
3269 | retval = -ENODEV; | 3259 | retval = -ENODEV; |
3270 | goto finished; | 3260 | goto err_irq; |
3271 | } | 3261 | } |
3272 | 3262 | ||
3273 | spin_lock_init(&dev->lock); | 3263 | spin_lock_init(&dev->lock); |
@@ -3283,10 +3273,8 @@ static int udc_pci_probe( | |||
3283 | 3273 | ||
3284 | if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { | 3274 | if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { |
3285 | dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq); | 3275 | dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq); |
3286 | kfree(dev); | ||
3287 | dev = NULL; | ||
3288 | retval = -EBUSY; | 3276 | retval = -EBUSY; |
3289 | goto finished; | 3277 | goto err_irq; |
3290 | } | 3278 | } |
3291 | dev->irq_registered = 1; | 3279 | dev->irq_registered = 1; |
3292 | 3280 | ||
@@ -3314,8 +3302,17 @@ static int udc_pci_probe( | |||
3314 | return 0; | 3302 | return 0; |
3315 | 3303 | ||
3316 | finished: | 3304 | finished: |
3317 | if (dev) | 3305 | udc_pci_remove(pdev); |
3318 | udc_pci_remove(pdev); | 3306 | return retval; |
3307 | |||
3308 | err_irq: | ||
3309 | iounmap(dev->virt_addr); | ||
3310 | err_ioremap: | ||
3311 | release_mem_region(resource, len); | ||
3312 | err_memreg: | ||
3313 | pci_disable_device(pdev); | ||
3314 | err_pcidev: | ||
3315 | kfree(dev); | ||
3319 | return retval; | 3316 | return retval; |
3320 | } | 3317 | } |
3321 | 3318 | ||
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 3dfada8d6061..f0f2b066ac08 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c | |||
@@ -2002,6 +2002,17 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, | |||
2002 | ep->udc = udc; | 2002 | ep->udc = udc; |
2003 | INIT_LIST_HEAD(&ep->queue); | 2003 | INIT_LIST_HEAD(&ep->queue); |
2004 | 2004 | ||
2005 | if (ep->index == 0) { | ||
2006 | ep->ep.caps.type_control = true; | ||
2007 | } else { | ||
2008 | ep->ep.caps.type_iso = ep->can_isoc; | ||
2009 | ep->ep.caps.type_bulk = true; | ||
2010 | ep->ep.caps.type_int = true; | ||
2011 | } | ||
2012 | |||
2013 | ep->ep.caps.dir_in = true; | ||
2014 | ep->ep.caps.dir_out = true; | ||
2015 | |||
2005 | if (i) | 2016 | if (i) |
2006 | list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); | 2017 | list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); |
2007 | 2018 | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c index 5c8f4effb62a..ccb9c213cc9f 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_core.c +++ b/drivers/usb/gadget/udc/bdc/bdc_core.c | |||
@@ -324,8 +324,7 @@ static void bdc_mem_free(struct bdc *bdc) | |||
324 | bdc->scratchpad.buff, bdc->scratchpad.sp_dma); | 324 | bdc->scratchpad.buff, bdc->scratchpad.sp_dma); |
325 | 325 | ||
326 | /* Destroy the dma pools */ | 326 | /* Destroy the dma pools */ |
327 | if (bdc->bd_table_pool) | 327 | dma_pool_destroy(bdc->bd_table_pool); |
328 | dma_pool_destroy(bdc->bd_table_pool); | ||
329 | 328 | ||
330 | /* Free the bdc_ep array */ | 329 | /* Free the bdc_ep array */ |
331 | kfree(bdc->bdc_ep_array); | 330 | kfree(bdc->bdc_ep_array); |
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 1379ad40d864..27af0f008b57 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c | |||
@@ -1348,6 +1348,7 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb, | |||
1348 | { | 1348 | { |
1349 | struct dummy *dum = dum_hcd->dum; | 1349 | struct dummy *dum = dum_hcd->dum; |
1350 | struct dummy_request *req; | 1350 | struct dummy_request *req; |
1351 | int sent = 0; | ||
1351 | 1352 | ||
1352 | top: | 1353 | top: |
1353 | /* if there's no request queued, the device is NAKing; return */ | 1354 | /* if there's no request queued, the device is NAKing; return */ |
@@ -1385,12 +1386,15 @@ top: | |||
1385 | if (len == 0) | 1386 | if (len == 0) |
1386 | break; | 1387 | break; |
1387 | 1388 | ||
1388 | /* use an extra pass for the final short packet */ | 1389 | /* send multiple of maxpacket first, then remainder */ |
1389 | if (len > ep->ep.maxpacket) { | 1390 | if (len >= ep->ep.maxpacket) { |
1390 | rescan = 1; | 1391 | is_short = 0; |
1391 | len -= (len % ep->ep.maxpacket); | 1392 | if (len % ep->ep.maxpacket) |
1393 | rescan = 1; | ||
1394 | len -= len % ep->ep.maxpacket; | ||
1395 | } else { | ||
1396 | is_short = 1; | ||
1392 | } | 1397 | } |
1393 | is_short = (len % ep->ep.maxpacket) != 0; | ||
1394 | 1398 | ||
1395 | len = dummy_perform_transfer(urb, req, len); | 1399 | len = dummy_perform_transfer(urb, req, len); |
1396 | 1400 | ||
@@ -1399,6 +1403,7 @@ top: | |||
1399 | req->req.status = len; | 1403 | req->req.status = len; |
1400 | } else { | 1404 | } else { |
1401 | limit -= len; | 1405 | limit -= len; |
1406 | sent += len; | ||
1402 | urb->actual_length += len; | 1407 | urb->actual_length += len; |
1403 | req->req.actual += len; | 1408 | req->req.actual += len; |
1404 | } | 1409 | } |
@@ -1421,7 +1426,7 @@ top: | |||
1421 | *status = -EOVERFLOW; | 1426 | *status = -EOVERFLOW; |
1422 | else | 1427 | else |
1423 | *status = 0; | 1428 | *status = 0; |
1424 | } else if (!to_host) { | 1429 | } else { |
1425 | *status = 0; | 1430 | *status = 0; |
1426 | if (host_len > dev_len) | 1431 | if (host_len > dev_len) |
1427 | req->req.status = -EOVERFLOW; | 1432 | req->req.status = -EOVERFLOW; |
@@ -1429,15 +1434,24 @@ top: | |||
1429 | req->req.status = 0; | 1434 | req->req.status = 0; |
1430 | } | 1435 | } |
1431 | 1436 | ||
1432 | /* many requests terminate without a short packet */ | 1437 | /* |
1438 | * many requests terminate without a short packet. | ||
1439 | * send a zlp if demanded by flags. | ||
1440 | */ | ||
1433 | } else { | 1441 | } else { |
1434 | if (req->req.length == req->req.actual | 1442 | if (req->req.length == req->req.actual) { |
1435 | && !req->req.zero) | 1443 | if (req->req.zero && to_host) |
1436 | req->req.status = 0; | 1444 | rescan = 1; |
1437 | if (urb->transfer_buffer_length == urb->actual_length | 1445 | else |
1438 | && !(urb->transfer_flags | 1446 | req->req.status = 0; |
1439 | & URB_ZERO_PACKET)) | 1447 | } |
1440 | *status = 0; | 1448 | if (urb->transfer_buffer_length == urb->actual_length) { |
1449 | if (urb->transfer_flags & URB_ZERO_PACKET && | ||
1450 | !to_host) | ||
1451 | rescan = 1; | ||
1452 | else | ||
1453 | *status = 0; | ||
1454 | } | ||
1441 | } | 1455 | } |
1442 | 1456 | ||
1443 | /* device side completion --> continuable */ | 1457 | /* device side completion --> continuable */ |
@@ -1460,7 +1474,7 @@ top: | |||
1460 | if (rescan) | 1474 | if (rescan) |
1461 | goto top; | 1475 | goto top; |
1462 | } | 1476 | } |
1463 | return limit; | 1477 | return sent; |
1464 | } | 1478 | } |
1465 | 1479 | ||
1466 | static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep) | 1480 | static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep) |
@@ -1890,7 +1904,7 @@ restart: | |||
1890 | default: | 1904 | default: |
1891 | treat_control_like_bulk: | 1905 | treat_control_like_bulk: |
1892 | ep->last_io = jiffies; | 1906 | ep->last_io = jiffies; |
1893 | total = transfer(dum_hcd, urb, ep, limit, &status); | 1907 | total -= transfer(dum_hcd, urb, ep, limit, &status); |
1894 | break; | 1908 | break; |
1895 | } | 1909 | } |
1896 | 1910 | ||
diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c index 8aa2593c2c36..b9429bc42511 100644 --- a/drivers/usb/gadget/udc/gr_udc.c +++ b/drivers/usb/gadget/udc/gr_udc.c | |||
@@ -2117,8 +2117,7 @@ static int gr_remove(struct platform_device *pdev) | |||
2117 | return -EBUSY; | 2117 | return -EBUSY; |
2118 | 2118 | ||
2119 | gr_dfs_delete(dev); | 2119 | gr_dfs_delete(dev); |
2120 | if (dev->desc_pool) | 2120 | dma_pool_destroy(dev->desc_pool); |
2121 | dma_pool_destroy(dev->desc_pool); | ||
2122 | platform_set_drvdata(pdev, NULL); | 2121 | platform_set_drvdata(pdev, NULL); |
2123 | 2122 | ||
2124 | gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req); | 2123 | gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req); |
diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c index 4c489692745e..dafe74eb9ade 100644 --- a/drivers/usb/gadget/udc/mv_u3d_core.c +++ b/drivers/usb/gadget/udc/mv_u3d_core.c | |||
@@ -1767,8 +1767,7 @@ static int mv_u3d_remove(struct platform_device *dev) | |||
1767 | usb_del_gadget_udc(&u3d->gadget); | 1767 | usb_del_gadget_udc(&u3d->gadget); |
1768 | 1768 | ||
1769 | /* free memory allocated in probe */ | 1769 | /* free memory allocated in probe */ |
1770 | if (u3d->trb_pool) | 1770 | dma_pool_destroy(u3d->trb_pool); |
1771 | dma_pool_destroy(u3d->trb_pool); | ||
1772 | 1771 | ||
1773 | if (u3d->ep_context) | 1772 | if (u3d->ep_context) |
1774 | dma_free_coherent(&dev->dev, u3d->ep_context_size, | 1773 | dma_free_coherent(&dev->dev, u3d->ep_context_size, |
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index 339af51df57d..81b6229c7805 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c | |||
@@ -2100,8 +2100,7 @@ static int mv_udc_remove(struct platform_device *pdev) | |||
2100 | } | 2100 | } |
2101 | 2101 | ||
2102 | /* free memory allocated in probe */ | 2102 | /* free memory allocated in probe */ |
2103 | if (udc->dtd_pool) | 2103 | dma_pool_destroy(udc->dtd_pool); |
2104 | dma_pool_destroy(udc->dtd_pool); | ||
2105 | 2104 | ||
2106 | if (udc->ep_dqh) | 2105 | if (udc->ep_dqh) |
2107 | dma_free_coherent(&pdev->dev, udc->ep_dqh_size, | 2106 | dma_free_coherent(&pdev->dev, udc->ep_dqh_size, |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 9a8c936cd42c..41f841fa6c4d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -1498,10 +1498,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, | |||
1498 | * use Event Data TRBs, and we don't chain in a link TRB on short | 1498 | * use Event Data TRBs, and we don't chain in a link TRB on short |
1499 | * transfers, we're basically dividing by 1. | 1499 | * transfers, we're basically dividing by 1. |
1500 | * | 1500 | * |
1501 | * xHCI 1.0 specification indicates that the Average TRB Length should | 1501 | * xHCI 1.0 and 1.1 specification indicates that the Average TRB Length |
1502 | * be set to 8 for control endpoints. | 1502 | * should be set to 8 for control endpoints. |
1503 | */ | 1503 | */ |
1504 | if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version == 0x100) | 1504 | if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100) |
1505 | ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8)); | 1505 | ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8)); |
1506 | else | 1506 | else |
1507 | ep_ctx->tx_info |= | 1507 | ep_ctx->tx_info |= |
@@ -1792,8 +1792,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) | |||
1792 | int size; | 1792 | int size; |
1793 | int i, j, num_ports; | 1793 | int i, j, num_ports; |
1794 | 1794 | ||
1795 | if (timer_pending(&xhci->cmd_timer)) | 1795 | del_timer_sync(&xhci->cmd_timer); |
1796 | del_timer_sync(&xhci->cmd_timer); | ||
1797 | 1796 | ||
1798 | /* Free the Event Ring Segment Table and the actual Event Ring */ | 1797 | /* Free the Event Ring Segment Table and the actual Event Ring */ |
1799 | size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); | 1798 | size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); |
@@ -2321,6 +2320,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |||
2321 | 2320 | ||
2322 | INIT_LIST_HEAD(&xhci->cmd_list); | 2321 | INIT_LIST_HEAD(&xhci->cmd_list); |
2323 | 2322 | ||
2323 | /* init command timeout timer */ | ||
2324 | setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout, | ||
2325 | (unsigned long)xhci); | ||
2326 | |||
2324 | page_size = readl(&xhci->op_regs->page_size); | 2327 | page_size = readl(&xhci->op_regs->page_size); |
2325 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 2328 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
2326 | "Supported page size register = 0x%x", page_size); | 2329 | "Supported page size register = 0x%x", page_size); |
@@ -2505,10 +2508,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |||
2505 | "Wrote ERST address to ir_set 0."); | 2508 | "Wrote ERST address to ir_set 0."); |
2506 | xhci_print_ir_set(xhci, 0); | 2509 | xhci_print_ir_set(xhci, 0); |
2507 | 2510 | ||
2508 | /* init command timeout timer */ | ||
2509 | setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout, | ||
2510 | (unsigned long)xhci); | ||
2511 | |||
2512 | /* | 2511 | /* |
2513 | * XXX: Might need to set the Interrupter Moderation Register to | 2512 | * XXX: Might need to set the Interrupter Moderation Register to |
2514 | * something other than the default (~1ms minimum between interrupts). | 2513 | * something other than the default (~1ms minimum between interrupts). |
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 5590eac2b22d..c79d33676672 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c | |||
@@ -180,51 +180,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) | |||
180 | "QUIRK: Resetting on resume"); | 180 | "QUIRK: Resetting on resume"); |
181 | } | 181 | } |
182 | 182 | ||
183 | /* | ||
184 | * In some Intel xHCI controllers, in order to get D3 working, | ||
185 | * through a vendor specific SSIC CONFIG register at offset 0x883c, | ||
186 | * SSIC PORT need to be marked as "unused" before putting xHCI | ||
187 | * into D3. After D3 exit, the SSIC port need to be marked as "used". | ||
188 | * Without this change, xHCI might not enter D3 state. | ||
189 | * Make sure PME works on some Intel xHCI controllers by writing 1 to clear | ||
190 | * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4 | ||
191 | */ | ||
192 | static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend) | ||
193 | { | ||
194 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
195 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
196 | u32 val; | ||
197 | void __iomem *reg; | ||
198 | |||
199 | if (pdev->vendor == PCI_VENDOR_ID_INTEL && | ||
200 | pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { | ||
201 | |||
202 | reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2; | ||
203 | |||
204 | /* Notify SSIC that SSIC profile programming is not done */ | ||
205 | val = readl(reg) & ~PROG_DONE; | ||
206 | writel(val, reg); | ||
207 | |||
208 | /* Mark SSIC port as unused(suspend) or used(resume) */ | ||
209 | val = readl(reg); | ||
210 | if (suspend) | ||
211 | val |= SSIC_PORT_UNUSED; | ||
212 | else | ||
213 | val &= ~SSIC_PORT_UNUSED; | ||
214 | writel(val, reg); | ||
215 | |||
216 | /* Notify SSIC that SSIC profile programming is done */ | ||
217 | val = readl(reg) | PROG_DONE; | ||
218 | writel(val, reg); | ||
219 | readl(reg); | ||
220 | } | ||
221 | |||
222 | reg = (void __iomem *) xhci->cap_regs + 0x80a4; | ||
223 | val = readl(reg); | ||
224 | writel(val | BIT(28), reg); | ||
225 | readl(reg); | ||
226 | } | ||
227 | |||
228 | #ifdef CONFIG_ACPI | 183 | #ifdef CONFIG_ACPI |
229 | static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) | 184 | static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) |
230 | { | 185 | { |
@@ -345,6 +300,51 @@ static void xhci_pci_remove(struct pci_dev *dev) | |||
345 | } | 300 | } |
346 | 301 | ||
347 | #ifdef CONFIG_PM | 302 | #ifdef CONFIG_PM |
303 | /* | ||
304 | * In some Intel xHCI controllers, in order to get D3 working, | ||
305 | * through a vendor specific SSIC CONFIG register at offset 0x883c, | ||
306 | * SSIC PORT need to be marked as "unused" before putting xHCI | ||
307 | * into D3. After D3 exit, the SSIC port need to be marked as "used". | ||
308 | * Without this change, xHCI might not enter D3 state. | ||
309 | * Make sure PME works on some Intel xHCI controllers by writing 1 to clear | ||
310 | * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4 | ||
311 | */ | ||
312 | static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend) | ||
313 | { | ||
314 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
315 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
316 | u32 val; | ||
317 | void __iomem *reg; | ||
318 | |||
319 | if (pdev->vendor == PCI_VENDOR_ID_INTEL && | ||
320 | pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { | ||
321 | |||
322 | reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2; | ||
323 | |||
324 | /* Notify SSIC that SSIC profile programming is not done */ | ||
325 | val = readl(reg) & ~PROG_DONE; | ||
326 | writel(val, reg); | ||
327 | |||
328 | /* Mark SSIC port as unused(suspend) or used(resume) */ | ||
329 | val = readl(reg); | ||
330 | if (suspend) | ||
331 | val |= SSIC_PORT_UNUSED; | ||
332 | else | ||
333 | val &= ~SSIC_PORT_UNUSED; | ||
334 | writel(val, reg); | ||
335 | |||
336 | /* Notify SSIC that SSIC profile programming is done */ | ||
337 | val = readl(reg) | PROG_DONE; | ||
338 | writel(val, reg); | ||
339 | readl(reg); | ||
340 | } | ||
341 | |||
342 | reg = (void __iomem *) xhci->cap_regs + 0x80a4; | ||
343 | val = readl(reg); | ||
344 | writel(val | BIT(28), reg); | ||
345 | readl(reg); | ||
346 | } | ||
347 | |||
348 | static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) | 348 | static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) |
349 | { | 349 | { |
350 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 350 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index a47a1e897086..43291f93afeb 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -302,6 +302,15 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) | |||
302 | ret = xhci_handshake(&xhci->op_regs->cmd_ring, | 302 | ret = xhci_handshake(&xhci->op_regs->cmd_ring, |
303 | CMD_RING_RUNNING, 0, 5 * 1000 * 1000); | 303 | CMD_RING_RUNNING, 0, 5 * 1000 * 1000); |
304 | if (ret < 0) { | 304 | if (ret < 0) { |
305 | /* we are about to kill xhci, give it one more chance */ | ||
306 | xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, | ||
307 | &xhci->op_regs->cmd_ring); | ||
308 | udelay(1000); | ||
309 | ret = xhci_handshake(&xhci->op_regs->cmd_ring, | ||
310 | CMD_RING_RUNNING, 0, 3 * 1000 * 1000); | ||
311 | if (ret == 0) | ||
312 | return 0; | ||
313 | |||
305 | xhci_err(xhci, "Stopped the command ring failed, " | 314 | xhci_err(xhci, "Stopped the command ring failed, " |
306 | "maybe the host is dead\n"); | 315 | "maybe the host is dead\n"); |
307 | xhci->xhc_state |= XHCI_STATE_DYING; | 316 | xhci->xhc_state |= XHCI_STATE_DYING; |
@@ -3461,8 +3470,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
3461 | if (start_cycle == 0) | 3470 | if (start_cycle == 0) |
3462 | field |= 0x1; | 3471 | field |= 0x1; |
3463 | 3472 | ||
3464 | /* xHCI 1.0 6.4.1.2.1: Transfer Type field */ | 3473 | /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */ |
3465 | if (xhci->hci_version == 0x100) { | 3474 | if (xhci->hci_version >= 0x100) { |
3466 | if (urb->transfer_buffer_length > 0) { | 3475 | if (urb->transfer_buffer_length > 0) { |
3467 | if (setup->bRequestType & USB_DIR_IN) | 3476 | if (setup->bRequestType & USB_DIR_IN) |
3468 | field |= TRB_TX_TYPE(TRB_DATA_IN); | 3477 | field |= TRB_TX_TYPE(TRB_DATA_IN); |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 6b0f4a47e402..9957bd96d4bc 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -146,7 +146,8 @@ static int xhci_start(struct xhci_hcd *xhci) | |||
146 | "waited %u microseconds.\n", | 146 | "waited %u microseconds.\n", |
147 | XHCI_MAX_HALT_USEC); | 147 | XHCI_MAX_HALT_USEC); |
148 | if (!ret) | 148 | if (!ret) |
149 | xhci->xhc_state &= ~XHCI_STATE_HALTED; | 149 | xhci->xhc_state &= ~(XHCI_STATE_HALTED | XHCI_STATE_DYING); |
150 | |||
150 | return ret; | 151 | return ret; |
151 | } | 152 | } |
152 | 153 | ||
@@ -654,15 +655,6 @@ int xhci_run(struct usb_hcd *hcd) | |||
654 | } | 655 | } |
655 | EXPORT_SYMBOL_GPL(xhci_run); | 656 | EXPORT_SYMBOL_GPL(xhci_run); |
656 | 657 | ||
657 | static void xhci_only_stop_hcd(struct usb_hcd *hcd) | ||
658 | { | ||
659 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
660 | |||
661 | spin_lock_irq(&xhci->lock); | ||
662 | xhci_halt(xhci); | ||
663 | spin_unlock_irq(&xhci->lock); | ||
664 | } | ||
665 | |||
666 | /* | 658 | /* |
667 | * Stop xHCI driver. | 659 | * Stop xHCI driver. |
668 | * | 660 | * |
@@ -677,12 +669,14 @@ void xhci_stop(struct usb_hcd *hcd) | |||
677 | u32 temp; | 669 | u32 temp; |
678 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 670 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
679 | 671 | ||
680 | if (!usb_hcd_is_primary_hcd(hcd)) { | 672 | if (xhci->xhc_state & XHCI_STATE_HALTED) |
681 | xhci_only_stop_hcd(xhci->shared_hcd); | ||
682 | return; | 673 | return; |
683 | } | ||
684 | 674 | ||
675 | mutex_lock(&xhci->mutex); | ||
685 | spin_lock_irq(&xhci->lock); | 676 | spin_lock_irq(&xhci->lock); |
677 | xhci->xhc_state |= XHCI_STATE_HALTED; | ||
678 | xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; | ||
679 | |||
686 | /* Make sure the xHC is halted for a USB3 roothub | 680 | /* Make sure the xHC is halted for a USB3 roothub |
687 | * (xhci_stop() could be called as part of failed init). | 681 | * (xhci_stop() could be called as part of failed init). |
688 | */ | 682 | */ |
@@ -717,6 +711,7 @@ void xhci_stop(struct usb_hcd *hcd) | |||
717 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 711 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
718 | "xhci_stop completed - status = %x", | 712 | "xhci_stop completed - status = %x", |
719 | readl(&xhci->op_regs->status)); | 713 | readl(&xhci->op_regs->status)); |
714 | mutex_unlock(&xhci->mutex); | ||
720 | } | 715 | } |
721 | 716 | ||
722 | /* | 717 | /* |
@@ -3793,6 +3788,9 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3793 | 3788 | ||
3794 | mutex_lock(&xhci->mutex); | 3789 | mutex_lock(&xhci->mutex); |
3795 | 3790 | ||
3791 | if (xhci->xhc_state) /* dying or halted */ | ||
3792 | goto out; | ||
3793 | |||
3796 | if (!udev->slot_id) { | 3794 | if (!udev->slot_id) { |
3797 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, | 3795 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, |
3798 | "Bad Slot ID %d", udev->slot_id); | 3796 | "Bad Slot ID %d", udev->slot_id); |
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 514a6cdaeff6..4a518ff12310 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -1051,6 +1051,7 @@ void musb_start(struct musb *musb) | |||
1051 | * (c) peripheral initiates, using SRP | 1051 | * (c) peripheral initiates, using SRP |
1052 | */ | 1052 | */ |
1053 | if (musb->port_mode != MUSB_PORT_MODE_HOST && | 1053 | if (musb->port_mode != MUSB_PORT_MODE_HOST && |
1054 | musb->xceiv->otg->state != OTG_STATE_A_WAIT_BCON && | ||
1054 | (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) { | 1055 | (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) { |
1055 | musb->is_active = 1; | 1056 | musb->is_active = 1; |
1056 | } else { | 1057 | } else { |
@@ -2448,6 +2449,9 @@ static int musb_suspend(struct device *dev) | |||
2448 | struct musb *musb = dev_to_musb(dev); | 2449 | struct musb *musb = dev_to_musb(dev); |
2449 | unsigned long flags; | 2450 | unsigned long flags; |
2450 | 2451 | ||
2452 | musb_platform_disable(musb); | ||
2453 | musb_generic_disable(musb); | ||
2454 | |||
2451 | spin_lock_irqsave(&musb->lock, flags); | 2455 | spin_lock_irqsave(&musb->lock, flags); |
2452 | 2456 | ||
2453 | if (is_peripheral_active(musb)) { | 2457 | if (is_peripheral_active(musb)) { |
@@ -2501,6 +2505,9 @@ static int musb_resume(struct device *dev) | |||
2501 | pm_runtime_disable(dev); | 2505 | pm_runtime_disable(dev); |
2502 | pm_runtime_set_active(dev); | 2506 | pm_runtime_set_active(dev); |
2503 | pm_runtime_enable(dev); | 2507 | pm_runtime_enable(dev); |
2508 | |||
2509 | musb_start(musb); | ||
2510 | |||
2504 | return 0; | 2511 | return 0; |
2505 | } | 2512 | } |
2506 | 2513 | ||
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index d07cafb7d5f5..e499b862a946 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c | |||
@@ -551,6 +551,9 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel) | |||
551 | } else { | 551 | } else { |
552 | cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE); | 552 | cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE); |
553 | 553 | ||
554 | /* delay to drain to cppi dma pipeline for isoch */ | ||
555 | udelay(250); | ||
556 | |||
554 | csr = musb_readw(epio, MUSB_RXCSR); | 557 | csr = musb_readw(epio, MUSB_RXCSR); |
555 | csr &= ~(MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_DMAENAB); | 558 | csr &= ~(MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_DMAENAB); |
556 | musb_writew(epio, MUSB_RXCSR, csr); | 559 | musb_writew(epio, MUSB_RXCSR, csr); |
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index a0cfead6150f..84512d1d5eee 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c | |||
@@ -225,8 +225,11 @@ static void dsps_musb_enable(struct musb *musb) | |||
225 | 225 | ||
226 | dsps_writel(reg_base, wrp->epintr_set, epmask); | 226 | dsps_writel(reg_base, wrp->epintr_set, epmask); |
227 | dsps_writel(reg_base, wrp->coreintr_set, coremask); | 227 | dsps_writel(reg_base, wrp->coreintr_set, coremask); |
228 | /* start polling for ID change. */ | 228 | /* start polling for ID change in dual-role idle mode */ |
229 | mod_timer(&glue->timer, jiffies + msecs_to_jiffies(wrp->poll_timeout)); | 229 | if (musb->xceiv->otg->state == OTG_STATE_B_IDLE && |
230 | musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) | ||
231 | mod_timer(&glue->timer, jiffies + | ||
232 | msecs_to_jiffies(wrp->poll_timeout)); | ||
230 | dsps_musb_try_idle(musb, 0); | 233 | dsps_musb_try_idle(musb, 0); |
231 | } | 234 | } |
232 | 235 | ||
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 39168fe9b406..b2685e75a683 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c | |||
@@ -379,6 +379,8 @@ static const struct of_device_id ux500_match[] = { | |||
379 | {} | 379 | {} |
380 | }; | 380 | }; |
381 | 381 | ||
382 | MODULE_DEVICE_TABLE(of, ux500_match); | ||
383 | |||
382 | static struct platform_driver ux500_driver = { | 384 | static struct platform_driver ux500_driver = { |
383 | .probe = ux500_probe, | 385 | .probe = ux500_probe, |
384 | .remove = ux500_remove, | 386 | .remove = ux500_remove, |
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 7d3beee2a587..173132416170 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig | |||
@@ -155,7 +155,7 @@ config USB_MSM_OTG | |||
155 | config USB_QCOM_8X16_PHY | 155 | config USB_QCOM_8X16_PHY |
156 | tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support" | 156 | tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support" |
157 | depends on ARCH_QCOM || COMPILE_TEST | 157 | depends on ARCH_QCOM || COMPILE_TEST |
158 | depends on RESET_CONTROLLER | 158 | depends on RESET_CONTROLLER && EXTCON |
159 | select USB_PHY | 159 | select USB_PHY |
160 | select USB_ULPI_VIEWPORT | 160 | select USB_ULPI_VIEWPORT |
161 | help | 161 | help |
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c index ec6ecd03269c..5320cb8642cb 100644 --- a/drivers/usb/phy/phy-generic.c +++ b/drivers/usb/phy/phy-generic.c | |||
@@ -232,7 +232,8 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop, | |||
232 | clk_rate = pdata->clk_rate; | 232 | clk_rate = pdata->clk_rate; |
233 | needs_vcc = pdata->needs_vcc; | 233 | needs_vcc = pdata->needs_vcc; |
234 | if (gpio_is_valid(pdata->gpio_reset)) { | 234 | if (gpio_is_valid(pdata->gpio_reset)) { |
235 | err = devm_gpio_request_one(dev, pdata->gpio_reset, 0, | 235 | err = devm_gpio_request_one(dev, pdata->gpio_reset, |
236 | GPIOF_ACTIVE_LOW, | ||
236 | dev_name(dev)); | 237 | dev_name(dev)); |
237 | if (!err) | 238 | if (!err) |
238 | nop->gpiod_reset = | 239 | nop->gpiod_reset = |
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c index 8a55b37d1a02..db68156568e6 100644 --- a/drivers/usb/phy/phy-isp1301.c +++ b/drivers/usb/phy/phy-isp1301.c | |||
@@ -31,6 +31,7 @@ static const struct i2c_device_id isp1301_id[] = { | |||
31 | { "isp1301", 0 }, | 31 | { "isp1301", 0 }, |
32 | { } | 32 | { } |
33 | }; | 33 | }; |
34 | MODULE_DEVICE_TABLE(i2c, isp1301_id); | ||
34 | 35 | ||
35 | static struct i2c_client *isp1301_i2c_client; | 36 | static struct i2c_client *isp1301_i2c_client; |
36 | 37 | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6d1941a2396a..6956c4f62216 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -278,6 +278,10 @@ static void option_instat_callback(struct urb *urb); | |||
278 | #define ZTE_PRODUCT_MF622 0x0001 | 278 | #define ZTE_PRODUCT_MF622 0x0001 |
279 | #define ZTE_PRODUCT_MF628 0x0015 | 279 | #define ZTE_PRODUCT_MF628 0x0015 |
280 | #define ZTE_PRODUCT_MF626 0x0031 | 280 | #define ZTE_PRODUCT_MF626 0x0031 |
281 | #define ZTE_PRODUCT_ZM8620_X 0x0396 | ||
282 | #define ZTE_PRODUCT_ME3620_MBIM 0x0426 | ||
283 | #define ZTE_PRODUCT_ME3620_X 0x1432 | ||
284 | #define ZTE_PRODUCT_ME3620_L 0x1433 | ||
281 | #define ZTE_PRODUCT_AC2726 0xfff1 | 285 | #define ZTE_PRODUCT_AC2726 0xfff1 |
282 | #define ZTE_PRODUCT_MG880 0xfffd | 286 | #define ZTE_PRODUCT_MG880 0xfffd |
283 | #define ZTE_PRODUCT_CDMA_TECH 0xfffe | 287 | #define ZTE_PRODUCT_CDMA_TECH 0xfffe |
@@ -544,6 +548,18 @@ static const struct option_blacklist_info zte_mc2716_z_blacklist = { | |||
544 | .sendsetup = BIT(1) | BIT(2) | BIT(3), | 548 | .sendsetup = BIT(1) | BIT(2) | BIT(3), |
545 | }; | 549 | }; |
546 | 550 | ||
551 | static const struct option_blacklist_info zte_me3620_mbim_blacklist = { | ||
552 | .reserved = BIT(2) | BIT(3) | BIT(4), | ||
553 | }; | ||
554 | |||
555 | static const struct option_blacklist_info zte_me3620_xl_blacklist = { | ||
556 | .reserved = BIT(3) | BIT(4) | BIT(5), | ||
557 | }; | ||
558 | |||
559 | static const struct option_blacklist_info zte_zm8620_x_blacklist = { | ||
560 | .reserved = BIT(3) | BIT(4) | BIT(5), | ||
561 | }; | ||
562 | |||
547 | static const struct option_blacklist_info huawei_cdc12_blacklist = { | 563 | static const struct option_blacklist_info huawei_cdc12_blacklist = { |
548 | .reserved = BIT(1) | BIT(2), | 564 | .reserved = BIT(1) | BIT(2), |
549 | }; | 565 | }; |
@@ -1591,6 +1607,14 @@ static const struct usb_device_id option_ids[] = { | |||
1591 | .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, | 1607 | .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, |
1592 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), | 1608 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), |
1593 | .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, | 1609 | .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, |
1610 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_L), | ||
1611 | .driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist }, | ||
1612 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_MBIM), | ||
1613 | .driver_info = (kernel_ulong_t)&zte_me3620_mbim_blacklist }, | ||
1614 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_X), | ||
1615 | .driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist }, | ||
1616 | { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ZM8620_X), | ||
1617 | .driver_info = (kernel_ulong_t)&zte_zm8620_x_blacklist }, | ||
1594 | { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, | 1618 | { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, |
1595 | { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, | 1619 | { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, |
1596 | { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, | 1620 | { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, |
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 6c3734d2b45a..d3ea90bef84d 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c | |||
@@ -80,6 +80,8 @@ static int whiteheat_firmware_download(struct usb_serial *serial, | |||
80 | static int whiteheat_firmware_attach(struct usb_serial *serial); | 80 | static int whiteheat_firmware_attach(struct usb_serial *serial); |
81 | 81 | ||
82 | /* function prototypes for the Connect Tech WhiteHEAT serial converter */ | 82 | /* function prototypes for the Connect Tech WhiteHEAT serial converter */ |
83 | static int whiteheat_probe(struct usb_serial *serial, | ||
84 | const struct usb_device_id *id); | ||
83 | static int whiteheat_attach(struct usb_serial *serial); | 85 | static int whiteheat_attach(struct usb_serial *serial); |
84 | static void whiteheat_release(struct usb_serial *serial); | 86 | static void whiteheat_release(struct usb_serial *serial); |
85 | static int whiteheat_port_probe(struct usb_serial_port *port); | 87 | static int whiteheat_port_probe(struct usb_serial_port *port); |
@@ -116,6 +118,7 @@ static struct usb_serial_driver whiteheat_device = { | |||
116 | .description = "Connect Tech - WhiteHEAT", | 118 | .description = "Connect Tech - WhiteHEAT", |
117 | .id_table = id_table_std, | 119 | .id_table = id_table_std, |
118 | .num_ports = 4, | 120 | .num_ports = 4, |
121 | .probe = whiteheat_probe, | ||
119 | .attach = whiteheat_attach, | 122 | .attach = whiteheat_attach, |
120 | .release = whiteheat_release, | 123 | .release = whiteheat_release, |
121 | .port_probe = whiteheat_port_probe, | 124 | .port_probe = whiteheat_port_probe, |
@@ -217,6 +220,34 @@ static int whiteheat_firmware_attach(struct usb_serial *serial) | |||
217 | /***************************************************************************** | 220 | /***************************************************************************** |
218 | * Connect Tech's White Heat serial driver functions | 221 | * Connect Tech's White Heat serial driver functions |
219 | *****************************************************************************/ | 222 | *****************************************************************************/ |
223 | |||
224 | static int whiteheat_probe(struct usb_serial *serial, | ||
225 | const struct usb_device_id *id) | ||
226 | { | ||
227 | struct usb_host_interface *iface_desc; | ||
228 | struct usb_endpoint_descriptor *endpoint; | ||
229 | size_t num_bulk_in = 0; | ||
230 | size_t num_bulk_out = 0; | ||
231 | size_t min_num_bulk; | ||
232 | unsigned int i; | ||
233 | |||
234 | iface_desc = serial->interface->cur_altsetting; | ||
235 | |||
236 | for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { | ||
237 | endpoint = &iface_desc->endpoint[i].desc; | ||
238 | if (usb_endpoint_is_bulk_in(endpoint)) | ||
239 | ++num_bulk_in; | ||
240 | if (usb_endpoint_is_bulk_out(endpoint)) | ||
241 | ++num_bulk_out; | ||
242 | } | ||
243 | |||
244 | min_num_bulk = COMMAND_PORT + 1; | ||
245 | if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk) | ||
246 | return -ENODEV; | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
220 | static int whiteheat_attach(struct usb_serial *serial) | 251 | static int whiteheat_attach(struct usb_serial *serial) |
221 | { | 252 | { |
222 | struct usb_serial_port *command_port; | 253 | struct usb_serial_port *command_port; |