[qca-nss-drv] Add New Frequency Support (600/800mhz) and Clean up

Clean up old method of adding frequencies and display, add new frequencies

Depends-on:29331

Crs-Fixed:none

Change-Id: Idf909a1f9fd13983b5bf50e971025c9a663b49bb
Signed-off-by: Thomas Wu <wthomas@codeaurora.org>
diff --git a/nss_freq.c b/nss_freq.c
index 188810b..de93637 100644
--- a/nss_freq.c
+++ b/nss_freq.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2015 The Linux Foundation. All rights reserved.
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * above copyright notice and this permission notice appear in all copies.
@@ -33,7 +33,7 @@
 
 /*
  * nss_freq_msg_init()
- *      Initialize the freq message
+ *	Initialize the freq message
  */
 static void nss_freq_msg_init(struct nss_corefreq_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len,
 			void *cb, void *app_data)
@@ -79,7 +79,7 @@
 	struct nss_corefreq_msg *ncm;
 	struct nss_freq_msg *nfc;
 
-	nss_info("%p: Frequency Changing to: %d\n", nss_ctx, eng);
+	nss_info("%p: frequency changing to: %d\n", nss_ctx, eng);
 
 	NSS_VERIFY_CTX_MAGIC(nss_ctx);
 	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
@@ -119,22 +119,31 @@
  * nss_freq_queue_work()
  *	Queue Work to the NSS Workqueue based on Current index.
  */
-static void nss_freq_queue_work(void)
+static int nss_freq_queue_work(void)
 {
+	uint32_t index = nss_runtime_samples.freq_scale_index;
 	BUG_ON(!nss_wq);
 
-	nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
+	nss_info("frequency:%d index:%d sample count:%x\n", nss_runtime_samples.freq_scale[index].frequency,
+					index, nss_runtime_samples.average);
 
 	nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
 	if (!nss_work) {
 		nss_info("NSS FREQ WQ kmalloc fail");
-		return;
+		return 1;
 	}
 
+	/*
+	 * Update proc node
+	 */
+	nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[index].frequency;
+
 	INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
-	nss_work->frequency = nss_cmd_buf.current_freq;
+	nss_work->frequency = nss_runtime_samples.freq_scale[index].frequency;
 	nss_work->stats_enable =  1;
+
 	queue_work(nss_wq, (struct work_struct *)nss_work);
+	return 0;
 }
 
 /*
@@ -146,9 +155,8 @@
 	uint32_t b_index;
 	uint32_t minimum;
 	uint32_t maximum;
-	uint32_t sample;
-
-	sample = core_stats->inst_cnt_total;
+	uint32_t sample = core_stats->inst_cnt_total;
+	uint32_t index = nss_runtime_samples.freq_scale_index;
 
 	/*
 	 * We do not accept any statistics if auto scaling is off,
@@ -187,57 +195,62 @@
 	nss_runtime_samples.average = nss_runtime_samples.sum / nss_runtime_samples.sample_count;
 
 	/*
-	 * Print out statistics every 10 seconds
+	 * Print out statistics every 10 samples
 	 */
-	if (nss_runtime_samples.message_rate_limit == NSS_MESSAGE_RATE_LIMIT) {
+	if (nss_runtime_samples.message_rate_limit++ >= NSS_MESSAGE_RATE_LIMIT) {
 		nss_trace("%p: Running AVG:%x Sample:%x Divider:%d\n", nss_ctx, nss_runtime_samples.average, core_stats->inst_cnt_total, nss_runtime_samples.sample_count);
-		nss_trace("%p: Current Frequency Index:%d\n", nss_ctx, nss_runtime_samples.freq_scale_index);
+		nss_trace("%p: Current Frequency Index:%d\n", nss_ctx, index);
 		nss_trace("%p: Auto Scale:%d Auto Scale Ready:%d\n", nss_ctx, nss_runtime_samples.freq_scale_ready, nss_cmd_buf.auto_scale);
 		nss_trace("%p: Current Rate:%x\n", nss_ctx, nss_runtime_samples.average);
 
 		nss_runtime_samples.message_rate_limit = 0;
-	} else {
-		nss_runtime_samples.message_rate_limit++;
 	}
 
 	/*
-	 * Scale Algorithmn UP and DOWN
+	 * Don't scale if we are not ready or auto scale is disabled.
 	 */
-	if ((nss_runtime_samples.freq_scale_ready == 1) && (nss_cmd_buf.auto_scale == 1)) {
-		if (nss_runtime_samples.freq_scale_rate_limit_up == NSS_FREQUENCY_SCALE_RATE_LIMIT_UP) {
-//			nss_info("%p: Preparing Switch Inst_Cnt Avg:%x\n", nss_ctx, nss_runtime_samples.average);
+	if ((nss_runtime_samples.freq_scale_ready != 1) || (nss_cmd_buf.auto_scale != 1)) {
+		return;
+	}
 
-			maximum = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].maximum;
+	/*
+	 * Scale Algorithmn
+	 *	Algorithmn will limit how fast it will transition each scale, by the number of samples seen.
+	 *	If any sample is out of scale during the idle count, the rate_limit will reset to 0.
+	 *	Scales are limited to the max number of cpu scales we support.
+	 */
+	if (nss_runtime_samples.freq_scale_rate_limit_up++ >= NSS_FREQUENCY_SCALE_RATE_LIMIT_UP) {
+		maximum = nss_runtime_samples.freq_scale[index].maximum;
+		if ((sample > maximum) && (index < (NSS_MAX_CPU_SCALES - 1))) {
+			nss_runtime_samples.freq_scale_index++;
+			nss_runtime_samples.freq_scale_ready = 0;
 
-			if ((sample > maximum) && (nss_runtime_samples.freq_scale_index < (nss_runtime_samples.freq_scale_sup_max - 1))) {
-				nss_runtime_samples.freq_scale_index++;
-				nss_runtime_samples.freq_scale_ready = 0;
-				nss_freq_queue_work();
-//				nss_info("%p: Switch Up with Sample %x \n", nss_ctx, sample);
-			} else {
-//				nss_info("%p: No Change at Max\n", nss_ctx);
-			}
-			nss_runtime_samples.freq_scale_rate_limit_up = 0;
-			return;
-
-		} else {
-			nss_runtime_samples.freq_scale_rate_limit_up++;
-		}
-
-		minimum = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].minimum;
-
-		if ((nss_runtime_samples.average < minimum) && (nss_runtime_samples.freq_scale_index > 0)) {
-			nss_runtime_samples.freq_scale_rate_limit_down++;
-
-			if (nss_runtime_samples.freq_scale_rate_limit_down == NSS_FREQUENCY_SCALE_RATE_LIMIT_DOWN) {
+			/*
+			 * If fail to increase frequency, decrease index
+			 */
+			if (nss_freq_queue_work()) {
 				nss_runtime_samples.freq_scale_index--;
-				nss_runtime_samples.freq_scale_ready = 0;
-				nss_freq_queue_work();
-				nss_runtime_samples.freq_scale_rate_limit_down = 0;
 			}
-		} else {
-			nss_runtime_samples.freq_scale_rate_limit_down = 0;
 		}
+		nss_runtime_samples.freq_scale_rate_limit_up = 0;
+		return;
+	}
+
+	if (nss_runtime_samples.freq_scale_rate_limit_down++ >= NSS_FREQUENCY_SCALE_RATE_LIMIT_DOWN) {
+		minimum = nss_runtime_samples.freq_scale[index].minimum;
+		if ((nss_runtime_samples.average < minimum) && (index > 0)) {
+			nss_runtime_samples.freq_scale_index--;
+			nss_runtime_samples.freq_scale_ready = 0;
+
+			/*
+			 * If fail to decrease frequency, increase index
+			 */
+			if (nss_freq_queue_work()) {
+				nss_runtime_samples.freq_scale_index++;
+			}
+		}
+		nss_runtime_samples.freq_scale_rate_limit_down = 0;
+		return;
 	}
 }