How to modify a patch for OpenWrt kernel 4.14?

I have a QMI patch for my board but it is for OpenWrt kernel 3. I want to patch it for kernel 4.14
How can I do it?
Thanks
Below is the patch file which is for kernel 3

--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -20,6 +20,73 @@
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc-wdm.h>
 
+#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;
+}
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 1))
+static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+    __be16 proto;
+    if (dev->udev->descriptor.idVendor != cpu_to_le16(0x2C7C))
+        return 1;
+    /* This check is no longer done by usbnet */
+    if (skb->len < dev->net->hard_header_len)
+        return 0;
+    switch (skb->data[0] & 0xf0)
+    {
+    case 0x40:
+        proto = htons(ETH_P_IP);
+        break;
+    case 0x60:
+        proto = htons(ETH_P_IPV6);
+        break;
+    case 0x00:
+        if (is_multicast_ether_addr(skb->data))
+            return 1;
+        /* possibly bogus destination - rewrite just in case */
+        skb_reset_mac_header(skb);
+        goto fix_dest;
+    default:
+        /* pass along other packets without modifications */
+        return 1;
+    }
+    if (skb_headroom(skb) < ETH_HLEN)
+        return 0;
+    skb_push(skb, ETH_HLEN);
+    skb_reset_mac_header(skb);
+    eth_hdr(skb)->h_proto = proto;
+    memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
+fix_dest:
+    memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
+    return 1;
+}
+/* very simplistic detection of IPv4 or IPv6 headers */
+static bool possibly_iphdr(const char *data)
+{
+    return (data[0] & 0xd0) == 0x40;
+}
+#endif
+#endif
+
+
+
 /* This driver supports wwan (3G/LTE/?) devices using a vendor
  * specific management protocol called Qualcomm MSM Interface (QMI) -
  * in addition to the more common AT commands over serial interface
@@ -332,6 +399,29 @@ next_desc:
        dev->net->dev_addr[0] &= 0xbf;    /* clear "IP" bit */
    }
    dev->net->netdev_ops = &qmi_wwan_netdev_ops;
+
+#if 1 // Added by Quectel
+        if (dev->udev->descriptor.idVendor == cpu_to_le16(0x2C7C))
+        {
+            dev_info(&intf->dev, "Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96&AG35 work on RawIP mode\n");
+            dev->net->flags |= IFF_NOARP;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 1))
+        /* make MAC addr easily distinguishable from an IP header */
+            if (possibly_iphdr(dev->net->dev_addr))
+            {
+                dev->net->dev_addr[0] |= 0x02; /* set local assignment bit */
+                dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */
+            }
+#endif
+            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;
 }
@@ -416,6 +506,10 @@ static const struct driver_info    qmi_wwan
    .unbind     = qmi_wwan_unbind,
    .manage_power   = qmi_wwan_manage_power,
    .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
@@ -434,6 +528,29 @@ static const struct driver_info    qmi_wwan
    QMI_FIXED_INTF(vend, prod, 0)
 
 static const struct usb_device_id products[] = {
+#if 1 //Added by Quectel
+#ifndef QMI_FIXED_INTF
+/* map QMI/wwan function by a fixed interface number */
+#define QMI_FIXED_INTF(vend, prod, num) \
+        .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, \
+   .idVendor = vend, \
+   .idProduct = prod, \
+   .bInterfaceClass = 0xff, \
+   .bInterfaceSubClass = 0xff, \
+   .bInterfaceProtocol = 0xff, \
+   .driver_info = (unsigned long)&qmi_wwan_force_int##num,
+#endif
+   { 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),
@@ -614,7 +731,7 @@ static const struct usb_device_id produc
    {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_GOBI_DEVICE(0x05c6, 0x9265)},  /* Asus Gobi 2000 Modem device (VR305) */
    {QMI_GOBI_DEVICE(0x05c6, 0x9235)},  /* Top Global Gobi 2000 Modem device (VR306) */
    {QMI_GOBI_DEVICE(0x05c6, 0x9275)},  /* iRex Technologies Gobi 2000 Modem device (VR307) */
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -530,6 +530,18 @@ static const struct option_blacklist_inf
 };
 
 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 */
+#endif
    { 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) },
@@ -1377,6 +1389,9 @@ static struct usb_serial_driver option_1
 #ifdef CONFIG_PM
    .suspend           = usb_wwan_suspend,
    .resume            = usb_wwan_resume,
+#if 1 //Added by Quectel
+   .reset_resume = usb_wwan_resume,
+#endif
 #endif
 };
 
@@ -1443,7 +1458,22 @@ static int option_probe(struct usb_seria
        dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
        iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
        return -ENODEV;
-
+#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->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
+            return -ENODEV;
+#endif
    /* Store device id so we can use it during attach. */
    usb_set_serial_data(serial, (void *)id);
 
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -78,7 +78,7 @@ static const struct usb_device_id id_tab
    {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) */
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -459,6 +459,20 @@ static struct urb *usb_wwan_setup_urb(st
              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;
 }

Below is the error I am getting after applying the patch (which is for kernel 3) in kernel 4.14

Applying /home/ubuntu/VNPT/ne25/openwrt/target/linux/ramips/patches-4.14/132-patch-kernel-driver-support-quectel-VNTECH-ER-BOARD.patch using plaintext:
patching file drivers/net/usb/qmi_wwan.c
Hunk #1 succeeded at 23 (offset 3 lines).
Hunk #2 FAILED at 399.
Hunk #3 succeeded at 910 with fuzz 1 (offset 427 lines).
Hunk #4 succeeded at 960 with fuzz 1 (offset 455 lines).
Hunk #5 FAILED at 708.
2 out of 5 hunks FAILED -- saving rejects to file drivers/net/usb/qmi_wwan.c.rej
patching file drivers/usb/serial/option.c
Hunk #1 succeeded at 579 with fuzz 1 (offset 49 lines).
Hunk #2 succeeded at 2104 (offset 715 lines).
Hunk #3 FAILED at 1458.
1 out of 3 hunks FAILED -- saving rejects to file drivers/usb/serial/option.c.rej
patching file drivers/usb/serial/qcserial.c
Hunk #1 succeeded at 92 (offset 14 lines).
patching file drivers/usb/serial/usb_wwan.c
Hunk #1 succeeded at 510 with fuzz 2 (offset 51 lines).
Patch failed!  Please fix /home/ubuntu/VNPT/ne25/openwrt/target/linux/ramips/patches-4.14/132-patch-kernel-driver-support-quectel-VNTECH-ER-BOARD.patch!
Makefile:26: recipe for target '/home/ubuntu/VNPT/ne25/openwrt/build_dir/target-mipsel_24kc_musl/linux-ramips_mt7621/linux-4.14.206/.prepared_6c91b06872cbc004c837cfcdcd3019e0' failed
make[4]: *** [/home/ubuntu/VNPT/ne25/openwrt/build_dir/target-mipsel_24kc_musl/linux-ramips_mt7621/linux-4.14.206/.prepared_6c91b06872cbc004c837cfcdcd3019e0] Error 1
make[4]: Leaving directory '/home/ubuntu/VNPT/ne25/openwrt/target/linux/ramips'
Makefile:13: recipe for target 'compile' failed
make[3]: *** [compile] Error 2
make[3]: Leaving directory '/home/ubuntu/VNPT/ne25/openwrt/target/linux'
time: target/linux/compile#7.66#2.98#9.30
target/Makefile:23: recipe for target 'target/linux/compile' failed
make[2]: *** [target/linux/compile] Error 2
make[2]: Leaving directory '/home/ubuntu/VNPT/ne25/openwrt'
target/Makefile:18: recipe for target '/home/ubuntu/VNPT/ne25/openwrt/staging_dir/target-mipsel_24kc_musl/stamp/.target_compile' failed
make[1]: *** [/home/ubuntu/VNPT/ne25/openwrt/staging_dir/target-mipsel_24kc_musl/stamp/.target_compile] Error 2
make[1]: Leaving directory '/home/ubuntu/VNPT/ne25/openwrt'
/home/ubuntu/VNPT/ne25/openwrt/include/toplevel.mk:216: recipe for target 'world' failed
make: *** [world] Error 2

I am unable to understand.

a patch is a modification of a source file.
if and when the text code differ from the original the patch wîll not apply.
It may be false at all and break the code.
it all depends of the content !

If you want to apply a patch for a specific file or version of a file, you must apply the modifications needed in the target version file too be same as in the original patched file...
then you can regenerate a new patch file for the unpatched target source code !

1 Like

You need to run "make target/linux/prepare" to download the kernel and apply the patch. See example at https://github.com/weikai/OpenWRT-NanoPi-R4S-X86-64-Builds/blob/main/steps/05_apply_post_config_patch.sh

1 Like

Thank you but it would be very helpful if you can give me the detailed steps.