return tmu->get_policy(res_thermal_name, policy);
}
+int pass_set_fault_around_bytes(struct pass_resource *res,
+ int fault_around_bytes)
+{
+ struct pass_resource_memory *memory;
+ char *res_name;
+ int res_type;
+
+ if (!res)
+ return -EINVAL;
+
+ res_name = res->cdata.res_name;
+ res_type = res->cdata.res_type;
+
+ switch (res_type) {
+ case PASS_RESOURCE_MEMORY_ID:
+ memory = res->hal.memory;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!memory->set_fault_around_bytes)
+ return -EINVAL;
+
+ return memory->set_fault_around_bytes(res_name, fault_around_bytes);
+}
+
+int pass_get_fault_around_bytes(struct pass_resource *res)
+{
+ struct pass_resource_memory *memory;
+ char *res_name;
+ int res_type;
+
+ if (!res)
+ return -EINVAL;
+
+ res_name = res->cdata.res_name;
+ res_type = res->cdata.res_type;
+
+ switch (res_type) {
+ case PASS_RESOURCE_MEMORY_ID:
+ memory = res->hal.memory;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!memory->get_fault_around_bytes)
+ return -EINVAL;
+
+ return memory->get_fault_around_bytes(res_name);
+}
+
int pass_set_pmqos_data(struct pass_resource *res, void *data)
{
struct pass_resource_nonstandard *nonstandard = NULL;
return 0;
}
+static int pass_save_memory_initdata(struct pass_resource *res)
+{
+ struct pass_resource_initdata *initdata = &res->initdata;
+
+ initdata->memory.fault_around_bytes = pass_get_fault_around_bytes(res);
+
+ return 0;
+}
+
static int pass_restore_dvfs_initdata(struct pass_resource *res)
{
struct pass_resource_initdata *initdata = &res->initdata;
return 0;
}
+static int pass_restore_memory_initdata(struct pass_resource *res)
+{
+ struct pass_resource_initdata *initdata = &res->initdata;
+ int fault_around_bytes = initdata->memory.fault_around_bytes;
+ int ret;
+
+ if (fault_around_bytes >= 0) {
+ ret = pass_set_fault_around_bytes(res, fault_around_bytes);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
int pass_save_initdata(struct pass_resource *res)
{
struct pass_conf_data *cdata;
}
break;
case PASS_RESOURCE_MEMORY_ID:
+ ret = pass_save_memory_initdata(res);
+ if (ret < 0) {
+ _E("Failed to save memory initdata for '%s' resource",
+ res_name);
+ return ret;
+ }
break;
case PASS_RESOURCE_NONSTANDARD_ID:
break;
}
break;
case PASS_RESOURCE_MEMORY_ID:
+ ret = pass_restore_memory_initdata(res);
+ if (ret < 0) {
+ _E("Failed to restore memory data for '%s' resource",
+ res_name);
+ return ret;
+ }
break;
case PASS_RESOURCE_NONSTANDARD_ID:
break;
*/
int pass_get_cpu_stats(struct pass_policy *policy);
+/***
+ * Functions for Memory h/w resource
+ */
+/* Get and set the /sys/kernel/debug/fault_around_bytes */
+int pass_get_fault_around_bytes(struct pass_resource *res);
+int pass_set_fault_around_bytes(struct pass_resource *res,
+ int fault_around_bytes);
+
/***
* Functions for Nonstandard H/W resources
*/
if (!result->section || !result->name || !result->value)
return 0;
+ /*
+ * Properties for the following h/w resources:
+ * - PASS_RESOURCE_CPU_ID
+ * - PASS_RESOURCE_BUS_ID
+ * - PASS_RESOURCE_GPU_ID
+ */
if (MATCH(result->name, "limit_max_freq"))
policy->pass_table[level].limit_max_freq = atoi(result->value);
else if (MATCH(result->name, "limit_min_freq"))
else if (MATCH(result->name, "limit_min_cpu"))
policy->pass_table[level].limit_min_cpu = atoi(result->value);
+ /*
+ * Properties for the following h/w resources:
+ * - PASS_RESOURCE_CPU_ID
+ */
else if (MATCH(result->name, "num_down_cond"))
policy->pass_table[level].num_down_cond = atoi(result->value);
else if (MATCH(result->name, "num_down_cond_freq"))
policy->pass_table[level].gov_timeout = gov_timeout;
}
+ /*
+ * Properties for the following h/w resources:
+ * - PASS_RESOURCE_MEMORY_ID
+ */
+ else if (MATCH(result->name, "fault_around_bytes"))
+ policy->pass_table[level].fault_around_bytes = atoi(result->value);
+
return 0;
}
cur->initdata.hotplug.online_state = NULL;
cur->initdata.hotplug.online_min_num = -1;
cur->initdata.hotplug.online_max_num = -1;
+
+ cur->initdata.memory.fault_around_bytes = -1;
}
} else {
_E("cannot parse the number of resource\n");
int limit_max_freq;
int limit_min_freq;
int limit_min_cpu;
+ int fault_around_bytes;
int ret;
if (new_level > policy->max_level)
if (new_level == curr_level)
return 0;
- /*
- * Get the max/min frequency and the number of max online
- * according to PASS level.
- */
+ /* Get the detailed resource value according to PASS level */
limit_max_freq = table[new_level].limit_max_freq;
limit_min_freq = table[new_level].limit_min_freq;
+ fault_around_bytes = table[new_level].fault_around_bytes;
policy->prev_level = curr_level;
policy->curr_level = new_level;
}
}
+ /* Set fault_around_bytes for the memory h/w */
+ if (fault_around_bytes) {
+ ret = pass_set_fault_around_bytes(res, fault_around_bytes);
+ if (ret < 0) {
+ _E("cannot set the fault_around_bytes of %s",
+ cdata->res_name);
+ return -EINVAL;
+ }
+ }
+
/*
_I("[PASS %s] Level %4s '%d->%d' : 'max %d | min %d'Hz/'%d'Core\n",
res->cdata.res_name,
* - PASS_RESOURCE_CPU_ID
* - PASS_RESOURCE_BUS_ID
* - PASS_RESOURCE_GPU_ID
+ * @fault_around_bytes: the number of bytes to be mapped around the fault
+ * this property is used for the following resoures:
+ * - PASS_RESOURCE_MEMORY_ID
*
* @gov_timeout: the period of timer for each PASS's level
* this property is used for the following resoures:
int limit_min_freq;
int limit_min_cpu;
+ int fault_around_bytes;
+
/* Properties for the timer */
double gov_timeout;
* - online_min_num: the initial minimum number of online resources
* - online_max_num: the initial maximum number of online resources
* @tmu: the initial value of tmu configuration
+ * @memory: the initial value of memory configuration
+ * - fault_around_bytes: the number of bytes to be mapped around the fault
*/
struct pass_resource_initdata {
struct {
struct {
/* NOTE: tmu has no writable data yet. */
} tmu;
+
+ struct {
+ int fault_around_bytes;
+ } memory;
};
/*