net: wireless: bcmdhd/bcmdhd_88: Time bound for dhd_dpc thread
Srinivas Ramachandran [Sat, 19 Nov 2016 01:04:07 +0000 (17:04 -0800)]
Add time bound for dhd_dpc thread. Ensures dpc thread does not
hog cpu, while at same time does not hurt perf. either.

Bug 1844359

Change-Id: I34b061ea495581ba92d249eaa34d992f1d54b6e6
Signed-off-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-on: http://git-master/r/1256652
Reviewed-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-by: Bhadram Varka <vbhadram@nvidia.com>
Reviewed-by: Narayan Reddy <narayanr@nvidia.com>
Tested-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-by: Vinayak Pane <vpane@nvidia.com>

drivers/net/wireless/bcmdhd/dhd_custom_sysfs_tegra_stat.c
drivers/net/wireless/bcmdhd/dhd_linux.c
drivers/net/wireless/bcmdhd/dhd_sdio.c
drivers/net/wireless/bcmdhd_88/dhd_custom_sysfs_tegra_stat.c
drivers/net/wireless/bcmdhd_88/dhd_linux.c
drivers/net/wireless/bcmdhd_88/dhd_sdio.c

index 259062a..bd84eb7 100644 (file)
@@ -341,6 +341,10 @@ tegra_sysfs_histogram_stat_show(struct device *dev,
 #endif
 }
 
+extern unsigned long dpc_sleep_cnt;
+extern atomic_t dpc_bound;
+extern atomic_t dpc_frame_time;
+
 ssize_t
 tegra_sysfs_histogram_stat_store(struct device *dev,
        struct device_attribute *attr,
@@ -385,6 +389,30 @@ tegra_sysfs_histogram_stat_store(struct device *dev,
                        buf + 15,
                        strlen(buf+15),
                        0);
+       } else if (strncmp(buf, "dpc_sleep_cnt", 13) == 0) {
+               pr_err("dpc_sleep_cnt: %ld\n", dpc_sleep_cnt);
+       } else if (strncmp(buf, "dpc_frame_time ", 15) == 0) {
+               err = kstrtouint(buf + 15, 0, &uint);
+               if (err < 0) {
+                       pr_err("%s: invalid dpc_frame_time (ms)\n", __func__);
+                       return count;
+               } else if (uint < 0 || uint < atomic_read(&dpc_bound)) {
+                       pr_err("%s: invalid dpc_frame_time (ms)\n", __func__);
+                   return count;
+               }
+               pr_info("%s: set dpc_frame_time (ms) %u\n", __func__, uint);
+               atomic_set(&dpc_frame_time, uint);
+       } else if (strncmp(buf, "dpc_bound ", 10) == 0) {
+               err = kstrtouint(buf + 10, 0, &uint);
+               if (err < 0) {
+                       pr_err("%s: invalid dpc_bound (ms)\n", __func__);
+                       return count;
+               } else if (uint < 0 || uint > atomic_read(&dpc_frame_time)) {
+                       pr_err("%s: invalid dpc_bound (ms)\n", __func__);
+                       return count;
+               }
+               pr_info("%s: set dpc_bound (ms) %u\n", __func__, uint);
+               atomic_set(&dpc_bound, uint);
        } else {
                pr_err("%s: unknown command\n", __func__);
        }
index 7f73c89..aeb95a5 100644 (file)
@@ -547,6 +547,11 @@ module_param_string(info_string, info_string, MOD_PARAM_INFOLEN, 0444);
 int op_mode = 0;
 int disable_proptx = 0;
 module_param(op_mode, int, 0644);
+
+unsigned long dpc_sleep_cnt;
+atomic_t dpc_bound = ATOMIC_INIT(8); /* ms */
+atomic_t dpc_frame_time = ATOMIC_INIT(16); /* ms */
+
 extern int wl_control_wl_start(struct net_device *dev);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(BCMLXSDMMC)
 struct semaphore dhd_registration_sem;
index 9a1b18a..a1ac188 100644 (file)
@@ -103,6 +103,7 @@ extern bool  bcmsdh_fatal_error(void *sdh);
 #endif
 
 #define DHD_TXMINMAX   1       /* Max tx frames if rx still pending */
+#define FRAME_TIME      16  /* Interframe interval for NV use cases */
 
 #define MEMBLOCK       2048            /* Block size used for downloading of dongle image */
 #define MAX_NVRAMBUF_SIZE      (6 * 1024) /* max nvram buf size */
@@ -5141,6 +5142,11 @@ dhdsdio_pr94636_WAR(dhd_bus_t *bus)
 }
 #endif /* SDHOST3 */
 /* Return TRUE if there may be more frames to read */
+
+extern unsigned long dpc_sleep_cnt;
+extern atomic_t dpc_bound;
+extern atomic_t dpc_frame_time;
+
 static uint
 dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 {
@@ -5166,6 +5172,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
        uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
        uint reorder_info_len;
        uint pkt_count;
+       ktime_t start_time, cur_time;
 
 #if defined(DHD_DEBUG) || defined(SDTEST)
        bool sdtest = FALSE;    /* To limit message spew from test mode */
@@ -5194,10 +5201,16 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
        /* Not finished unless we encounter no more frames indication */
        *finished = FALSE;
 
-
+       start_time = ktime_get();
        for (rxseq = bus->rx_seq, rxleft = maxframes;
             !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
             rxseq++, rxleft--) {
+               cur_time = ktime_get();
+               if (ktime_to_ms(ktime_sub(cur_time, start_time))
+                               > atomic_read(&dpc_bound)) {
+                       ++dpc_sleep_cnt;
+                       osl_sleep(atomic_read(&dpc_frame_time) - atomic_read(&dpc_bound));
+               }
 #ifdef DHDTCPACK_SUP_DBG
                if (bus->dhd->tcpack_sup_mode != TCPACK_SUP_DELAYTX) {
                        if (bus->dotxinrx == FALSE)
@@ -5216,7 +5229,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
                } else if (bus->dotxinrx && (bus->clkstate == CLK_AVAIL) &&
                        !bus->fcstate && DATAOK(bus) &&
                        (pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres)) {
-                       dhdsdio_sendfromq(bus, dhd_txbound);
+                       dhdsdio_sendfromq(bus, dhd_txminmax);
 #ifdef DHDTCPACK_SUPPRESS
                        /* In TCPACK_SUP_DELAYTX mode, do txinrx only if
                         * 1. Any DATA packet to TX
index fcc8bdc..f8c9b29 100644 (file)
@@ -342,6 +342,10 @@ tegra_sysfs_histogram_stat_show(struct device *dev,
 #endif
 }
 
+extern unsigned long dpc_sleep_cnt;
+extern atomic_t dpc_bound;
+extern atomic_t dpc_frame_time;
+
 ssize_t
 tegra_sysfs_histogram_stat_store(struct device *dev,
        struct device_attribute *attr,
@@ -386,6 +390,30 @@ tegra_sysfs_histogram_stat_store(struct device *dev,
                        (unsigned char *) buf + 15,
                        strlen(buf+15),
                        0);
+       } else if (strncmp(buf, "dpc_sleep_cnt", 13) == 0) {
+               pr_err("dpc_sleep_cnt: %ld\n", dpc_sleep_cnt);
+       } else if (strncmp(buf, "dpc_frame_time ", 15) == 0) {
+               err = kstrtouint(buf + 15, 0, &uint);
+               if (err < 0) {
+                       pr_err("%s: invalid dpc_frame_time (ms)\n", __func__);
+                       return count;
+               } else if (uint < 0 || uint < atomic_read(&dpc_bound)) {
+                       pr_err("%s: invalid dpc_frame_time (ms)\n", __func__);
+                       return count;
+               }
+               pr_info("%s: set dpc_frame_time (ms) %u\n", __func__, uint);
+               atomic_set(&dpc_frame_time, uint);
+       } else if (strncmp(buf, "dpc_bound ", 10) == 0) {
+               err = kstrtouint(buf + 10, 0, &uint);
+               if (err < 0) {
+                       pr_err("%s: invalid dpc_bound (ms)\n", __func__);
+                       return count;
+               } else if (uint < 0 || uint > atomic_read(&dpc_frame_time)) {
+                       pr_err("%s: invalid dpc_bound (ms)\n", __func__);
+                       return count;
+               }
+               pr_info("%s: set dpc_bound (ms) %u\n", __func__, uint);
+               atomic_set(&dpc_bound, uint);
        } else {
                pr_err("%s: unknown command\n", __func__);
        }
index 28d110a..31bb874 100644 (file)
@@ -412,6 +412,11 @@ module_param_string(info_string, info_string, MOD_PARAM_INFOLEN, 0444);
 int op_mode = 0;
 int disable_proptx = 0;
 module_param(op_mode, int, 0644);
+
+unsigned long dpc_sleep_cnt;
+atomic_t dpc_bound = ATOMIC_INIT(8); /* ms */
+atomic_t dpc_frame_time = ATOMIC_INIT(16); /* ms */
+
 extern int wl_control_wl_start(struct net_device *dev);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
 struct semaphore dhd_registration_sem;
index ea82e80..dccdb0f 100644 (file)
@@ -5331,6 +5331,9 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
        return num;
 }
 
+extern unsigned long dpc_sleep_cnt;
+extern atomic_t dpc_bound;
+extern atomic_t dpc_frame_time;
 
 /* Return TRUE if there may be more frames to read */
 static uint
@@ -5358,6 +5361,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
        uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
        uint reorder_info_len;
        uint pkt_count;
+       ktime_t start_time, cur_time;
 
 #if defined(DHD_DEBUG) || defined(SDTEST)
        bool sdtest = FALSE;    /* To limit message spew from test mode */
@@ -5386,10 +5390,16 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
        /* Not finished unless we encounter no more frames indication */
        *finished = FALSE;
 
-
+       start_time = ktime_get();
        for (rxseq = bus->rx_seq, rxleft = maxframes;
             !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
             rxseq++, rxleft--) {
+               cur_time = ktime_get();
+               if (ktime_to_ms(ktime_sub(cur_time, start_time))
+                               > atomic_read(&dpc_bound)) {
+                       ++dpc_sleep_cnt;
+                       osl_sleep(atomic_read(&dpc_frame_time) - atomic_read(&dpc_bound));
+               }
 
 #ifdef DHDTHREAD
                /* tx more to improve rx performance */