gl-infra-builder-FUjr/patches-wlan-ap/0014-ipq807x-fix-usb-modem-driver-for-gl.patch
Jianhui Zhao 3fbc3ec336 ax1800/axt1800: upgrade wlan-ap to v2.6.0
Signed-off-by: Jianhui Zhao <jianhui.zhao@gl-inet.com>
2022-07-12 16:43:39 +08:00

340 lines
15 KiB
Diff

From 6faf6bac518f866657ccf6583531804006181c0c Mon Sep 17 00:00:00 2001
From: Jianhui Zhao <jianhui.zhao@gl-inet.com>
Date: Tue, 12 Jul 2022 12:22:33 +0800
Subject: [PATCH] ipq807x: fix usb modem driver for gl
Signed-off-by: Jianhui Zhao <jianhui.zhao@gl-inet.com>
---
.../patches/203-fix-usb-modem-driver.patch | 319 ++++++++++++++++++
1 file changed, 319 insertions(+)
create mode 100644 feeds/ipq807x/ipq807x/patches/203-fix-usb-modem-driver.patch
diff --git a/feeds/ipq807x/ipq807x/patches/203-fix-usb-modem-driver.patch b/feeds/ipq807x/ipq807x/patches/203-fix-usb-modem-driver.patch
new file mode 100644
index 00000000..b3f109d2
--- /dev/null
+++ b/feeds/ipq807x/ipq807x/patches/203-fix-usb-modem-driver.patch
@@ -0,0 +1,319 @@
+--- linux-4.4.60.orig/drivers/net/usb/qmi_wwan.c
++++ linux-4.4.60/drivers/net/usb/qmi_wwan.c
+@@ -58,6 +58,24 @@ static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3};
+
+ static const u8 buggy_fw_addr[ETH_ALEN] = {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00};
+
++#if 1 //Added by Quectel
++#include <linux/etherdevice.h>
++struct sk_buff *qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
++{
++ if (dev->udev->descriptor.idVendor != cpu_to_le16(0x2C7C))
++ return skb;
++ // Skip Ethernet header from message
++ if (skb_pull(skb, ETH_HLEN)) {
++ return skb;
++ } else {
++ dev_err(&dev->intf->dev, "Packet Dropped ");
++ }
++ // Filter the packet out, release it
++ dev_kfree_skb_any(skb);
++ return NULL;
++}
++#endif
++
+ /* Make up an ethernet header if the packet doesn't have one.
+ *
+ * A firmware bug common among several devices cause them to send raw
+@@ -294,6 +312,21 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
+ dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */
+ }
+ dev->net->netdev_ops = &qmi_wwan_netdev_ops;
++ //dev->net->sysfs_groups[0] = &qmi_wwan_sysfs_attr_group;
++#if 1 //Added by Quectel
++ if (dev->udev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
++ dev_info(&intf->dev, "QuectelEC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96&AG35 work on RawIP mode\n");
++ dev->net->flags |= IFF_NOARP;
++ usb_control_msg(
++ interface_to_usbdev(intf),
++ usb_sndctrlpipe(interface_to_usbdev(intf), 0),
++ 0x22, //USB_CDC_REQ_SET_CONTROL_LINE_STATE
++ 0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
++ 1, //active CDC DTR
++ intf->cur_altsetting->desc.bInterfaceNumber,
++ NULL, 0, 100);
++ }
++#endif
+ err:
+ return status;
+ }
+@@ -378,7 +411,11 @@ static const struct driver_info qmi_wwan_info = {
+ .bind = qmi_wwan_bind,
+ .unbind = qmi_wwan_unbind,
+ .manage_power = qmi_wwan_manage_power,
+- .rx_fixup = qmi_wwan_rx_fixup,
++ //.rx_fixup = qmi_wwan_rx_fixup,
++ #if 1 //Added by Quectel
++ .tx_fixup = qmi_wwan_tx_fixup,
++ .rx_fixup = qmi_wwan_rx_fixup,
++ #endif
+ };
+
+ #define HUAWEI_VENDOR_ID 0x12D1
+@@ -397,6 +434,18 @@ static const struct driver_info qmi_wwan_info = {
+ QMI_FIXED_INTF(vend, prod, 0)
+
+ static const struct usb_device_id products[] = {
++#if 1 //Added by Quectel
++ { QMI_FIXED_INTF(0x05C6, 0x9003, 4) }, /* Quectel UC20 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0125, 4) }, /* Quectel EC25 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0121, 4) }, /* Quectel EC21 */
++ { QMI_FIXED_INTF(0x05C6, 0x9215, 4) }, /* Quectel EC20 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0191, 4) }, /* Quectel EG91 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0195, 4) }, /* Quectel EG95 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0306, 4) }, /* Quectel EG06/EP06/EM06 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0296, 4) }, /* Quectel BG96 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0435, 4) }, /* Quectel AG35 */
++#endif
++
+ /* 1. CDC ECM like devices match on the control interface */
+ { /* Huawei E392, E398 and possibly others sharing both device id and more... */
+ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 9),
+@@ -753,6 +802,8 @@ static const struct usb_device_id products[] = {
+ {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
+ {QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
+ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
++ {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */
++ {QMI_FIXED_INTF(0x1e0e, 0x9001, 5)}, /* SIMCom 7230E */
+ {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */
+
+ /* 4. Gobi 1000 devices */
+@@ -783,7 +834,7 @@ static const struct usb_device_id products[] = {
+ {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */
+ {QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */
+ {QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */
+- {QMI_GOBI_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
++// {QMI_GOBI_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
+ {QMI_FIXED_INTF(0x05c6, 0x9215, 4)}, /* Quectel EC20 Mini PCIe */
+ {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */
+ {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */
+--- linux-4.4.60.orig/drivers/usb/serial/option.c
++++ linux-4.4.60/drivers/usb/serial/option.c
+@@ -241,6 +241,7 @@ static void option_instat_callback(struct urb *urb);
+ /* These Quectel products use Quectel's vendor ID */
+ #define QUECTEL_PRODUCT_EC21 0x0121
+ #define QUECTEL_PRODUCT_EC25 0x0125
++#define QUECTEL_PRODUCT_EP06 0x0306
+
+ #define CMOTECH_VENDOR_ID 0x16d8
+ #define CMOTECH_PRODUCT_6001 0x6001
+@@ -541,6 +542,23 @@ static void option_instat_callback(struct urb *urb);
+ #define WETELECOM_PRODUCT_6802 0x6802
+ #define WETELECOM_PRODUCT_WMD300 0x6803
+
++#define LONGSUNG_PRODUCT_U9300C 0x9b3c
++
++/* FORGE PRODUCT */
++#define FORGE_VENDOR_ID 0x05c6
++
++#define FORGE_PRODUCT_SLM750 0xf601
++
++/* NODECOM PRODUCT */
++#define NODECOM_VENDOR_ID 0x1508
++
++#define NODECOM_PRODUCT_NL660 0x1001
++
++/* NEOWAY PRODUCT */
++#define NEOWAY_VENDOR_ID 0x2949
++
++#define NEOWAY_PRODUCT_N720 0x8243
++
+ struct option_blacklist_info {
+ /* bitmask of interface numbers blacklisted for send_setup */
+ const unsigned long sendsetup;
+@@ -670,6 +688,27 @@ static const struct option_blacklist_info cinterion_rmnet2_blacklist = {
+ };
+
+ static const struct usb_device_id option_ids[] = {
++#if 1 //Added by Quectel
++ { USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */
++ { USB_DEVICE(0x05C6, 0x9003) }, /* Quectel UC20 */
++ { USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25 */
++ { USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21 */
++ { USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20 */
++ { USB_DEVICE(0x2C7C, 0x0191) }, /* Quectel EG91 */
++ { USB_DEVICE(0x2C7C, 0x0195) }, /* Quectel EG95 */
++ { USB_DEVICE(0x2C7C, 0x0306) }, /* Quectel EG06/EP06/EM06 */
++ { USB_DEVICE(0x2C7C, 0x0296) }, /* Quectel BG96 */
++ { USB_DEVICE(0x2C7C, 0x0435) }, /* Quectel AG35 */
++ { USB_DEVICE(0x2C7C, 0x6026) }, /* Quectel AG35 */
++#endif
++ { USB_DEVICE(0x19d2, 0x0536) },/* MZ386 */
++ { USB_DEVICE(0x19d2, 0x0117) },
++ { USB_DEVICE(0x19d2, 0x0199) },
++ { USB_DEVICE(0x19d2, 0x1476) },
++ { USB_DEVICE(LONGCHEER_VENDOR_ID, LONGSUNG_PRODUCT_U9300C) },
++ { USB_DEVICE(FORGE_VENDOR_ID, FORGE_PRODUCT_SLM750) },
++ { USB_DEVICE(NODECOM_VENDOR_ID, NODECOM_PRODUCT_NL660) },
++ { USB_DEVICE(NEOWAY_VENDOR_ID, NEOWAY_PRODUCT_N720) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
+@@ -1178,6 +1217,8 @@ static const struct usb_device_id option_ids[] = {
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
++ { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06),
++ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
+@@ -2057,6 +2098,9 @@ static struct usb_serial_driver option_1port_device = {
+ #ifdef CONFIG_PM
+ .suspend = usb_wwan_suspend,
+ .resume = usb_wwan_resume,
++#if 1 //Added by Quectel
++ .reset_resume = usb_wwan_resume,
++#endif
+ #endif
+ };
+
+@@ -2072,6 +2116,8 @@ static int option_probe(struct usb_serial *serial,
+ struct usb_interface_descriptor *iface_desc =
+ &serial->interface->cur_altsetting->desc;
+ struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
++
++ //unsigned long device_flags = id->driver_info;
+ const struct option_blacklist_info *blacklist;
+
+ /* Never bind to the CD-Rom emulation interface */
+@@ -2092,13 +2138,91 @@ static int option_probe(struct usb_serial *serial,
+ * a separate module.
+ */
+ if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) &&
+- dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
+- iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
++ dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
++ iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
+ return -ENODEV;
+
+ /* Store the blacklist info so we can use it during attach. */
+- usb_set_serial_data(serial, (void *)blacklist);
+-
++ //usb_set_serial_data(serial, (void *)blacklist);
++#if 1 //Added by Quectel
++ //Quectel UC20's interface 4 can be used as USB network device
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && \
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9003) \
++ && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
++ return -ENODEV;
++ //Quectel EC20's interface 4 can be used as USB network device
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && \
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9215) \
++ && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
++ return -ENODEV;
++ //Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96/AG35's interface 4 can be used as USB network device
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C) && \
++ serial->dev->descriptor.idProduct != cpu_to_le16(0x6026) \
++ && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
++ return -ENODEV;
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C) && \
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x6026) \
++ && serial->interface->cur_altsetting->desc.bInterfaceNumber<= 1)
++ return -ENODEV;
++#endif
++#if 0 //Added by Quectel
++ //For USB Auto Suspend
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9090)) {
++ pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
++ usb_enable_autosuspend(serial->dev);
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)) {
++ pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
++ usb_enable_autosuspend(serial->dev);
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)) {
++ pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
++ usb_set_serial_data(serial, (void *)device_flags);
++ usb_enable_autosuspend(serial->dev);
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C) &&
++ serial->dev->descriptor.idProduct != cpu_to_le16(0x0306)) {
++ pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
++ usb_enable_autosuspend(serial->dev);
++ }
++#endif
++#if 0 //Added by Quectel
++ //For USB Remote Wakeup
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9090)) {
++ device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)) {
++ device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)) {
++ device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
++ device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
++ }
++#endif
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x19d2) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x1476) &&
++ serial->interface->cur_altsetting->desc. bInterfaceNumber == 3)
++ return -ENODEV;
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x19d2) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x1476) &&
++ serial->interface->cur_altsetting->desc. bInterfaceNumber == 4)
++ return -ENODEV;
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x19d2) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x1509) &&
++ serial->interface->cur_altsetting->desc. bInterfaceNumber == 4)
++ return -ENODEV;
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x19d2) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x1509) &&
++ serial->interface->cur_altsetting->desc. bInterfaceNumber == 5)
++ return -ENODEV;
+ return 0;
+ }
+
+--- linux-4.4.60.orig/drivers/usb/serial/qcserial.c
++++ linux-4.4.60/drivers/usb/serial/qcserial.c
+@@ -92,7 +92,7 @@ static const struct usb_device_id id_table[] = {
+ {USB_DEVICE(0x03f0, 0x241d)}, /* HP Gobi 2000 QDL device (VP412) */
+ {USB_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */
+ {USB_DEVICE(0x05c6, 0x9214)}, /* Acer Gobi 2000 QDL device (VP413) */
+- {USB_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
++// {USB_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
+ {USB_DEVICE(0x05c6, 0x9264)}, /* Asus Gobi 2000 QDL device (VR305) */
+ {USB_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */
+ {USB_DEVICE(0x05c6, 0x9234)}, /* Top Global Gobi 2000 QDL device (VR306) */
+--- linux-4.4.60.orig/drivers/usb/serial/usb_wwan.c
++++ linux-4.4.60/drivers/usb/serial/usb_wwan.c
+@@ -504,7 +504,19 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, endpoint) | dir,
+ buf, len, callback, ctx);
+-
++#if 1 //Added by Quectel for zero packet
++ if (dir == USB_DIR_OUT) {
++ struct usb_device_descriptor *desc = &serial->dev->descriptor;
++ if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9090))
++ urb->transfer_flags |= URB_ZERO_PACKET;
++ if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9003))
++ urb->transfer_flags |= URB_ZERO_PACKET;
++ if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9215))
++ urb->transfer_flags |= URB_ZERO_PACKET;
++ if (desc->idVendor == cpu_to_le16(0x2C7C))
++ urb->transfer_flags |= URB_ZERO_PACKET;
++ }
++#endif
+ return urb;
+ }
+
--
2.25.1