| From 2a8cdfde9237c4e1bd7c2e68c415b006491d23cc Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Thu, 6 Nov 2014 18:08:33 +0100 |
| Subject: USB: cdc-acm: add quirk for control-line state requests |
| |
| From: Johan Hovold <johan@kernel.org> |
| |
| commit 2a8cdfde9237c4e1bd7c2e68c415b006491d23cc upstream. |
| |
| Add new quirk for devices that cannot handle control-line state |
| requests. |
| |
| Note that we currently send these requests to all devices, regardless of |
| whether they claim to support it, but that errors are only logged if |
| support is claimed. |
| |
| Since commit 0943d8ead30e ("USB: cdc-acm: use tty-port dtr_rts"), which |
| only changed the timings for these requests slightly, this has been |
| reported to cause occasional firmware crashes on Simtec Electronics |
| Entropy Key devices after re-enumeration. Enable the quirk for this |
| device. |
| |
| Reported-by: Nix <nix@esperi.org.uk> |
| Tested-by: Nix <nix@esperi.org.uk> |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/class/cdc-acm.c | 14 ++++++++++++-- |
| drivers/usb/class/cdc-acm.h | 2 ++ |
| 2 files changed, 14 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/usb/class/cdc-acm.c |
| +++ b/drivers/usb/class/cdc-acm.c |
| @@ -145,8 +145,15 @@ static int acm_ctrl_msg(struct acm *acm, |
| /* devices aren't required to support these requests. |
| * the cdc acm descriptor tells whether they do... |
| */ |
| -#define acm_set_control(acm, control) \ |
| - acm_ctrl_msg(acm, USB_CDC_REQ_SET_CONTROL_LINE_STATE, control, NULL, 0) |
| +static inline int acm_set_control(struct acm *acm, int control) |
| +{ |
| + if (acm->quirks & QUIRK_CONTROL_LINE_STATE) |
| + return -EOPNOTSUPP; |
| + |
| + return acm_ctrl_msg(acm, USB_CDC_REQ_SET_CONTROL_LINE_STATE, |
| + control, NULL, 0); |
| +} |
| + |
| #define acm_set_line(acm, line) \ |
| acm_ctrl_msg(acm, USB_CDC_REQ_SET_LINE_CODING, 0, line, sizeof *(line)) |
| #define acm_send_break(acm, ms) \ |
| @@ -1315,6 +1322,7 @@ made_compressed_probe: |
| tty_port_init(&acm->port); |
| acm->port.ops = &acm_port_ops; |
| init_usb_anchor(&acm->delayed); |
| + acm->quirks = quirks; |
| |
| buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); |
| if (!buf) { |
| @@ -1682,6 +1690,8 @@ static const struct usb_device_id acm_id |
| { USB_DEVICE(0x0572, 0x1328), /* Shiro / Aztech USB MODEM UM-3100 */ |
| .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
| }, |
| + { USB_DEVICE(0x20df, 0x0001), /* Simtec Electronics Entropy Key */ |
| + .driver_info = QUIRK_CONTROL_LINE_STATE, }, |
| { USB_DEVICE(0x2184, 0x001c) }, /* GW Instek AFG-2225 */ |
| { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ |
| }, |
| --- a/drivers/usb/class/cdc-acm.h |
| +++ b/drivers/usb/class/cdc-acm.h |
| @@ -121,6 +121,7 @@ struct acm { |
| unsigned int throttle_req:1; /* throttle requested */ |
| u8 bInterval; |
| struct usb_anchor delayed; /* writes queued for a device about to be woken */ |
| + unsigned long quirks; |
| }; |
| |
| #define CDC_DATA_INTERFACE_TYPE 0x0a |
| @@ -132,3 +133,4 @@ struct acm { |
| #define NOT_A_MODEM BIT(3) |
| #define NO_DATA_INTERFACE BIT(4) |
| #define IGNORE_DEVICE BIT(5) |
| +#define QUIRK_CONTROL_LINE_STATE BIT(6) |