[9610] drivers: modem_if: Add GRO to SIT modem interface
authorJiyoung Jeong <ji_0.jeong@samsung.com>
Tue, 23 Oct 2018 12:15:38 +0000 (21:15 +0900)
committerDongsik Son <dongsik.son@samsung.com>
Wed, 24 Oct 2018 13:20:51 +0000 (22:20 +0900)
Change-Id: I1a1e3d83b703ec39be3d11f789f5e2f0acfc0221
Signed-off-by: Jiyoung Jeong <ji_0.jeong@samsung.com>
drivers/misc/modem_if/Kconfig
drivers/misc/modem_if/modem_io_device.c
drivers/misc/modem_if/modem_link_device_shmem.c
drivers/misc/modem_if/modem_link_device_shmem.h
drivers/misc/modem_if/modem_prj.h

index d17d6bcd4b1160bc79b934080cf5def47350aeaa..adcc42f9f5305a1bcd556be1fd2dcb028a9bb4b4 100644 (file)
@@ -49,6 +49,13 @@ config MODEM_IF_ADAPTIVE_QOS
        bool "Enable Adaptive QOS for high data performance"
        default n
 
+config MODEM_IF_NET_GRO
+       bool "enable GRO feature"
+       depends on LINK_DEVICE_NAPI
+       default n
+       ---help---
+        This enables GRO(Generic Receive Offload) feature
+
 config UART_SWITCH
        bool "UART SWITCH Support"
        default n
index 7394ef7bab040e774863064596ab6446e2b618ac..b93738ae2edfd2b29ffc53ef821f5365423f51bf 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/if_arp.h>
 #include <linux/ip.h>
+#include <linux/ipv6.h>
 #include <linux/if_ether.h>
 #include <linux/etherdevice.h>
 #include <linux/device.h>
@@ -29,7 +30,7 @@
 
 #include "modem_prj.h"
 #include "modem_utils.h"
-
+#include "modem_link_device_shmem.h"
 
 static u16 exynos_build_fr_config(struct io_device *iod, struct link_device *ld,
                unsigned int count);
@@ -311,12 +312,34 @@ static int rx_raw_misc(struct sk_buff *skb)
        return 0;
 }
 
+#ifdef CONFIG_LINK_DEVICE_NAPI
+#ifdef CONFIG_MODEM_IF_NET_GRO
+static int check_gro_support(struct sk_buff *skb)
+{
+       switch (skb->data[0] & 0xF0) {
+       case 0x40:
+               return (ip_hdr(skb)->protocol == IPPROTO_TCP);
+
+       case 0x60:
+               return (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP);
+       }
+       return 0;
+}
+#else
+static int check_gro_support(struct sk_buff *skb)
+{
+       return 0;
+}
+#endif
+#endif
+
 static int rx_multi_pdp(struct sk_buff *skb)
 {
        struct link_device *ld = skbpriv(skb)->ld;
        struct io_device *iod = skbpriv(skb)->iod;
        struct net_device *ndev;
        struct iphdr *iphdr;
+       struct shmem_link_device *shmd = to_shmem_link_device(ld);
        int ret;
 
        ndev = iod->ndev;
@@ -353,10 +376,23 @@ static int rx_multi_pdp(struct sk_buff *skb)
        }
 
 #ifdef CONFIG_LINK_DEVICE_NAPI
-       ret = netif_receive_skb(skb);
-       if (ret != NET_RX_SUCCESS) {
-               mif_err("%s->%s: ERR! netif_receive_skb (err %d)\n",
-                       ld->name, iod->name, ret);
+       skb_reset_network_header(skb);
+
+       if (check_gro_support(skb)) {
+               ret = napi_gro_receive(&shmd->mld_napi, skb);
+               if (ret == GRO_DROP) {
+                       mif_err_limited("%s: %s<-%s: ERR! napi_gro_receive\n",
+                               ld->name, iod->name, iod->mc->name);
+               }
+
+               if (ld->gro_flush)
+                       ld->gro_flush(ld);
+       } else {
+               ret = netif_receive_skb(skb);
+               if (ret != NET_RX_SUCCESS) {
+                       mif_err_limited("%s->%s: ERR! netif_receive_skb (err %d)\n",
+                               ld->name, iod->name, ret);
+               }
        }
 #else /* !CONFIG_LINK_DEVICE_NAPI */
        if (in_interrupt())
@@ -1546,6 +1582,9 @@ static void vnet_setup(struct net_device *ndev)
        ndev->tx_queue_len = 1000;
        ndev->mtu = ETH_DATA_LEN;
        ndev->watchdog_timeo = 5 * HZ;
+#ifdef CONFIG_MODEM_IF_NET_GRO
+       ndev->features |= NETIF_F_GRO;
+#endif
 }
 
 static void vnet_setup_ether(struct net_device *ndev)
@@ -1559,6 +1598,9 @@ static void vnet_setup_ether(struct net_device *ndev)
        ndev->tx_queue_len = 1000;
        ndev->mtu = ETH_DATA_LEN;
        ndev->watchdog_timeo = 5 * HZ;
+#ifdef CONFIG_MODEM_IF_NET_GRO
+       ndev->features |= NETIF_F_GRO;
+#endif
 }
 
 static u16 exynos_build_fr_config(struct io_device *iod, struct link_device *ld,
index d87a8a08399bcb6bc0ae3984b64f8680eb9a13f3..3c4ed5fed949187d08c209a2713774d9bd794215 100644 (file)
@@ -2526,6 +2526,31 @@ static int shmem_crash_reason(struct link_device *ld, struct io_device *iod,
        return 0;
 }
 
+#ifdef CONFIG_MODEM_IF_NET_GRO
+static long gro_flush_time = 100000L;
+module_param(gro_flush_time, long, 0644);
+
+static void gro_flush_timer(struct link_device *ld)
+{
+       struct shmem_link_device *shmd = to_shmem_link_device(ld);
+       struct timespec curr, diff;
+
+       if (!gro_flush_time)
+               return;
+
+       if (unlikely(shmd->flush_time.tv_sec == 0)) {
+               getnstimeofday(&shmd->flush_time);
+       } else {
+               getnstimeofday(&(curr));
+               diff = timespec_sub(curr, shmd->flush_time);
+               if ((diff.tv_sec > 0) || (diff.tv_nsec > gro_flush_time)) {
+                       napi_gro_flush(&shmd->mld_napi, false);
+                       getnstimeofday(&shmd->flush_time);
+               }
+       }
+}
+#endif
+
 #ifdef CONFIG_LINK_DEVICE_NAPI
 /*
  * shmd_rx_int_poll
@@ -2806,6 +2831,10 @@ struct link_device *shmem_create_link_device(struct platform_device *pdev)
        ld->acpm_dump = save_acpm_dump;
 
        ld->crash_reason = shmem_crash_reason;
+#ifdef CONFIG_MODEM_IF_NET_GRO
+       ld->gro_flush = gro_flush_timer;
+#endif
+
 #ifdef CONFIG_LINK_DEVICE_NAPI
        ld->enable_rx_int = shmem_enable_rx_int;
        ld->disable_rx_int = shmem_disable_rx_int;
index 5fb757a19f35d710bf583791aa06d72f5cf53007..2a3e3ac0c6f1bd7e39533e5877a270585d439124 100644 (file)
@@ -237,6 +237,10 @@ struct shmem_link_device {
        unsigned int rx_poll_count;
        unsigned long long rx_int_disabled_time;
 #endif /* CONFIG_LINK_DEVICE_NAPI */
+
+#ifdef CONFIG_MODEM_IF_NET_GRO
+       struct timespec flush_time;
+#endif
 };
 
 /* converts from struct link_device* to struct xxx_link_device* */
index a97977e32e6f3e0ef75b501417819f13bb0da67f..9f7660fec193f96b0b5de285261deae3bd6aad0f 100644 (file)
@@ -25,6 +25,9 @@
 #include <linux/spinlock.h>
 #include <linux/cdev.h>
 #include <linux/types.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+
 #include "include/modem_v1.h"
 #include "include/exynos_ipc.h"
 
@@ -650,6 +653,7 @@ struct link_device {
        int (*enable_rx_int)(struct link_device *ld);
        int (*disable_rx_int)(struct link_device *ld);
 #endif /* CONFIG_LINK_DEVICE_NAPI */
+       void (*gro_flush)(struct link_device *ld);
 };
 
 /** rx_alloc_skb - allocate an skbuff and set skb's iod, ld