@@ -32,6 +32,11 @@ enum qcserial_layouts {
QCSERIAL_SWI_SDX55_RMNET = 7, /* Sierra Wireless SDX55 */
};
+enum qcserial_flags {
+ QC_SENDSETUP = (1 << 0),
+ QC_ZLP = (1 << 1),
+};
+
#define DEVICE_G1K(v, p) \
USB_DEVICE(v, p), .driver_info = QCSERIAL_G1K
#define DEVICE_SWI(v, p) \
@@ -262,7 +267,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
__u8 nintf;
__u8 ifnum;
int altsetting = -1;
- bool sendsetup = false;
+ unsigned long flags = 0;
/* we only support vendor specific functions */
if (intf->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
@@ -301,6 +306,9 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
/* default to enabling interface */
altsetting = 0;
+ /* default to enabling ZLP */
+ flags |= QC_ZLP;
+
/*
* Composite mode; don't bind to the QMI/net interface as that
* gets handled by other drivers.
@@ -386,11 +394,11 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
break;
case 2:
dev_dbg(dev, "NMEA GPS interface found\n");
- sendsetup = true;
+ flags |= QC_SENDSETUP;
break;
case 3:
dev_dbg(dev, "Modem port found\n");
- sendsetup = true;
+ flags |= QC_SENDSETUP;
break;
default:
/* don't claim any unsupported interface */
@@ -446,11 +454,11 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
switch (ifnum) {
case 2:
dev_dbg(dev, "Modem port found\n");
- sendsetup = true;
+ flags |= QC_SENDSETUP;
break;
case 3:
dev_dbg(dev, "NMEA GPS interface found\n");
- sendsetup = true;
+ flags |= QC_SENDSETUP;
break;
case 4:
dev_dbg(dev, "DM/DIAG interface found\n");
@@ -475,11 +483,11 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
switch (ifnum) {
case 0:
dev_dbg(dev, "Modem port found\n");
- sendsetup = true;
+ flags |= QC_SENDSETUP;
break;
case 1:
dev_dbg(dev, "NMEA GPS interface found\n");
- sendsetup = true;
+ flags |= QC_SENDSETUP;
break;
case 2:
dev_dbg(dev, "DM/DIAG interface found\n");
@@ -502,7 +510,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
switch (ifnum) {
case 3:
dev_dbg(dev, "Modem port found\n");
- sendsetup = true;
+ flags |= QC_SENDSETUP;
break;
case 4:
dev_dbg(dev, "DM/DIAG interface found\n");
@@ -522,7 +530,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
switch (ifnum) {
case 1:
dev_dbg(dev, "Modem port found\n");
- sendsetup = true;
+ flags |= QC_SENDSETUP;
break;
case 2:
dev_dbg(dev, "DM/DIAG interface found\n");
@@ -551,7 +559,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
}
if (!retval)
- usb_set_serial_data(serial, (void *)(unsigned long)sendsetup);
+ usb_set_serial_data(serial, (void *)flags);
return retval;
}
@@ -559,15 +567,17 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
static int qc_attach(struct usb_serial *serial)
{
struct usb_wwan_intf_private *data;
- bool sendsetup;
+ unsigned long flags = 0;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- sendsetup = !!(unsigned long)(usb_get_serial_data(serial));
- if (sendsetup)
+ flags = (unsigned long)(usb_get_serial_data(serial));
+ if (flags & QC_SENDSETUP)
data->use_send_setup = 1;
+ if (flags & QC_ZLP)
+ data->use_zlp = 1;
spin_lock_init(&data->susp_lock);
This is a port of the corresponding change from the qcserial.c driver distributed as part of the 9X50 SDK, tested using author's own EM7565 device. The SDK qcserial.c driver enables ZLP unconditionally, however this was found to break QDL mode (as exercised by the qmi-firmware-update tool from libqmi[1], as well as the SDK-provided firmware update utility). Thus, ZLP is limited to non-QDL interfaces. [1]: https://www.freedesktop.org/wiki/Software/libqmi/ Signed-off-by: Ivan Shapovalov <intelfx@intelfx.name> --- drivers/usb/serial/qcserial.c | 36 ++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-)