resource_34xx.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 1,309 行 · 第 1/3 页

C
1,309
字号
	}	/* Increment the number of users for this domain. */	resp->no_of_users++;	return ret;ret:	up_srfmutex(&users_list_mutex);	return ret;}/* Deletes the request from the list of request for the given resource.*//* Recalulates the target level to be set for the resource and updates it *//* if not same as the current level.Also calls notification functions for *//* registered users to notify the target level change			*/int resource_release(struct res_handle *res){	struct  shared_resource *resp;	struct  users_list *user, *cur_user = NULL;	unsigned short target_level;	int ret = 0;	if (res == ERR_PTR(-ENOENT)) {		DPRINTK("Invalid resource handle passed to reource_release\n");		return ret;	}	resp = res->res;	DPRINTK("resource_request: Clock-name %s\n", res->usr_name);	down_srfmutex(&users_list_mutex);	if (res->usr_index != -1)		cur_user = &usr_list[res->usr_index];	else		goto ret;	ret = resp->validate(resp, cur_user->level, DEFAULT_LEVEL);	if (ret) {		DPRINTK("Validation failed\n");		ret = -EINVAL;		goto ret;	}	/* Delete the resource */	DPRINTK("Deleting resource for %s\n", resp->name);	list_del(&cur_user->node);	usr_flag[cur_user->index] = UNUSED;	usr_list[cur_user->index].usr_name = NULL;	usr_list[cur_user->index].level = DEFAULT_LEVEL;	usr_list[cur_user->index].index = cur_user->index;	res->usr_index = -1;	/* Regenerate the target_level for the resource */	target_level = DEFAULT_LEVEL;	list_for_each_entry(user, &(resp->users_list), node) {		if (user->level > target_level)			target_level = user->level;		}	DPRINTK("New Target level is %d\n", target_level);	up_srfmutex(&users_list_mutex);	if ((target_level == DEFAULT_LEVEL) &&			(resp->prcm_id == PRCM_VDD1_CONSTRAINT))		target_level = CO_VDD1_OPP1;	else if ((target_level == DEFAULT_LEVEL) &&			 (resp->prcm_id == PRCM_VDD2_CONSTRAINT))		target_level = CO_VDD2_OPP2;	else if ((target_level == DEFAULT_LEVEL) &&			(resp->prcm_id == PRCM_ARMFREQ_CONSTRAINT))		target_level = min_arm_freq;	else if ((target_level == DEFAULT_LEVEL) &&			(resp->prcm_id == PRCM_DSPFREQ_CONSTRAINT))		target_level = min_dsp_freq;	if (target_level != resp->curr_level) {		DPRINTK("Changing Level for resource %s to %d\n",			resp->name, target_level);		if ((resp->res_type != RES_FREQ_CO) &&\			(target_level < MAX_LEVEL))			atomic_notifier_call_chain(				&resp->pre_notifier_list[target_level],				target_level, NULL);		down_srfmutex(&resp->res_action_sem);		ret = resp->action(resp, resp->curr_level, target_level);		up_srfmutex(&resp->res_action_sem);		if (ret)			printk(KERN_ERR "FATAL ERROR: Unable to Change "					"level for resource %s to %d\n",						resp->name, target_level);		else			/* If successful, change the resource curr_level */			resp->curr_level = target_level;		if ((resp->res_type != RES_FREQ_CO) &&				(target_level < MAX_LEVEL))			atomic_notifier_call_chain(				&resp->post_notifier_list[target_level],				target_level, NULL);	}	/* Decrement the number of users for this domain. */	resp->no_of_users--;	return ret;ret:	up_srfmutex(&users_list_mutex);	return ret;}/* Frees the res_handle structure from the pool */void resource_put(struct res_handle *res){	if (res == ERR_PTR(-ENOENT)) {		DPRINTK("Invalid resource handle passed to resource_put\n");		return;	}	if (res->usr_index != -1) {		printk(KERN_ERR "resource_put called before "				"resource_release\n");		return;	}	down_srfmutex(&res_handle_mutex);	DPRINTK("resource_put for %s, index = %d\n",			res->res->name, res->res_index);	handle_flag[res->res_index] = UNUSED;	handle_list[res->res_index].res = NULL;	handle_list[res->res_index].usr_name = NULL;	handle_list[res->res_index].res_index = res->res_index;	handle_list[res->res_index].usr_index = -1;	up_srfmutex(&res_handle_mutex);}/* Registers a notification function from a resource user for a specific  *//* target level. The function is called before a level change for the     *//* resource to the target level.					  */void resource_register_pre_notification(struct res_handle *res,			struct notifier_block *nb, unsigned short target_level){	struct shared_resource *resp;	int ind;	resp = res->res;	DPRINTK("Notification registered for %s, level %d\n",		resp->name, target_level);	if (target_level == resp->max_levels) {		for (ind = DEFAULT_LEVEL; ind < resp->max_levels; ind++) {			res->nb_internal_pre[ind] =				(struct notifier_block *)kmalloc(sizeof(struct notifier_block), GFP_KERNEL);			*(res->nb_internal_pre[ind]) = *nb;			atomic_notifier_chain_register(				&resp->pre_notifier_list[ind],				res->nb_internal_pre[ind]);		}		}	else {		res->nb_internal_pre[target_level] =			(struct notifier_block *)			kmalloc(sizeof(struct notifier_block), GFP_KERNEL);		*(res->nb_internal_pre[target_level]) = *nb;		atomic_notifier_chain_register(				&resp->pre_notifier_list[target_level],					res->nb_internal_pre[target_level]);	}}/* Registers a notification function from a resource user for a specific  *//* target level. The function is called before a level change for the     *//* resource to the target level.					  */void resource_register_post_notification(struct res_handle *res,			struct notifier_block *nb, unsigned short target_level){	struct shared_resource *resp;	int ind;	resp = res->res;	DPRINTK("Notification registered for %s, level %d\n",		resp->name, target_level);	if (target_level == resp->max_levels) {		for (ind = DEFAULT_LEVEL; ind < resp->max_levels; ind++) {			res->nb_internal_post[ind] =				(struct notifier_block *)				kmalloc(sizeof(struct notifier_block), GFP_KERNEL);			*(res->nb_internal_post[ind]) = *nb;			atomic_notifier_chain_register(				&resp->post_notifier_list[ind],				res->nb_internal_post[ind]);		}		}	else {		res->nb_internal_post[target_level] =			(struct notifier_block *)			kmalloc(sizeof(struct notifier_block), GFP_KERNEL);		*(res->nb_internal_post[target_level]) = *nb;		atomic_notifier_chain_register(			&resp->post_notifier_list[target_level],			res->nb_internal_post[target_level]);	}}/* Unregisters the notification function from a resource user for a specific  *//* target level.    							      */void resource_unregister_pre_notification(struct res_handle *res,			struct notifier_block *nb, unsigned short target_level){	struct shared_resource *resp;	int ind, ret;	resp = res->res;	DPRINTK("Notification unregistered for %s, level %d\n",		resp->name, target_level);	if (target_level == resp->max_levels) {		for (ind = DEFAULT_LEVEL; ind < resp->max_levels; ind++) {			ret = atomic_notifier_chain_unregister(				&resp->pre_notifier_list[ind],				res->nb_internal_pre[ind]);			if (ret != -ENOENT)				kfree(res->nb_internal_pre[ind]);		}	} else {		ret = atomic_notifier_chain_unregister(			&resp->pre_notifier_list[target_level],			res->nb_internal_pre[target_level]);		if (ret != -ENOENT)			kfree(res->nb_internal_pre[target_level]);	}}/* Unregisters the notification function from a resource user for a specific  *//* target level.    							      */void resource_unregister_post_notification(struct res_handle *res,			struct notifier_block *nb, unsigned short target_level){	struct shared_resource *resp;	int ind, ret;	resp = res->res;	DPRINTK("Notification unregistered for %s, level %d\n",		resp->name, target_level);	if (target_level == resp->max_levels) {		for (ind = DEFAULT_LEVEL; ind < resp->max_levels; ind++) {			ret = atomic_notifier_chain_unregister(				&resp->post_notifier_list[ind],				res->nb_internal_post[ind]);			if (ret != -ENOENT)				kfree(res->nb_internal_post[ind]);		}	} else {		ret = atomic_notifier_chain_unregister(				&resp->post_notifier_list[target_level],				res->nb_internal_post[target_level]);		if (ret != -ENOENT)			kfree(res->nb_internal_post[target_level]);		}}/* Returns the current level for a resource */int resource_get_level(struct res_handle *res){	struct shared_resource *resp;	int ret;	resp = res->res;	down_srfmutex(&res_handle_mutex);	ret = resp->curr_level;	up_srfmutex(&res_handle_mutex);	return ret;}/* Activation function to change target level for a Power Domain resource *//* Transtitions from RET to OFF and OFF to RET are not allowed 		  */int activate_power_res(struct shared_resource *resp,		       unsigned short current_level,		       unsigned short target_level){	int ret = 0;	unsigned long prcm_id = resp->prcm_id;	/* Common code for transitioning to RET/OFF. */	switch (target_level) {	case POWER_DOMAIN_RET:	case POWER_DOMAIN_OFF:		if (current_level != POWER_DOMAIN_ON) {			ret = prcm_set_power_domain_state(prcm_id,						POWER_DOMAIN_ON, PRCM_FORCE);			if (ret != PRCM_PASS)				return ret;		}		break;	}	switch (target_level) {	case POWER_DOMAIN_ON:			ret = prcm_set_power_domain_state(prcm_id,						POWER_DOMAIN_ON, PRCM_FORCE);			break;	case POWER_DOMAIN_RET:	case POWER_DOMAIN_OFF:		ret = prcm_set_power_domain_state(prcm_id,					POWER_DOMAIN_RET, PRCM_FORCE);		break;	default:		ret = PRCM_FAIL;	}	return ret;}/* Activation function to change target level for a Logical resource */int activate_logical_res(struct shared_resource *resp,			 unsigned short current_level,			 unsigned short target_level){	unsigned long prcm_id = resp->prcm_id;	switch (prcm_id) {	case DOM_CORE1:		core_active = (target_level)?LOGICAL_USED:LOGICAL_UNUSED;		break;	default:		return -1;	}	return 0;}/* Function to change target level for Memory or Logic resource */int activate_memory_logic(struct shared_resource *resp,			 unsigned short current_level,			 unsigned short target_level){	unsigned long domain_id;	unsigned long prcm_id = resp->prcm_id;	domain_id = DOMAIN_ID(prcm_id);	switch (prcm_id) {	case PRCM_CORE_MEM1ON:		prcm_set_memory_resource_on_state(target_level);		break;	case PRCM_CORE_MEM2ON:		prcm_set_memory_resource_on_state(target_level);		break;	case PRCM_CORE_MEM1RET:		break;	case PRCM_CORE_MEM2RET:		break;	case PRCM_CORE_LOGICRET:		break;	default :		DPRINTK("Unsupported resourse\n");		return -1;	}	return 0;}/* Functio to validate the memory or logic resource transition */int validate_memory_logic(struct shared_resource *resp,			 unsigned short current_level,			 unsigned short target_level){	if (target_level >= resp->max_levels)		return -1;	return 0;}int activate_autoidle_resource(struct shared_resource *resp,			unsigned short current_level,			 unsigned short target_level){	unsigned long prcm_id = resp->prcm_id;	int ret;	ret = prcm_dpll_clock_auto_control(prcm_id, target_level);	if (ret == PRCM_FAIL) {		DPRINTK("Invalid DPLL Autoidle resource state\n");		return -1;	}	return 0;}int validate_autoidle_resource(struct shared_resource *resp,			unsigned short current_level,			unsigned short target_level){	int invalidlevelmin = 2, invalidlevelmax = 4;	if (target_level >= resp->max_levels) {		printk(KERN_ERR"Invalid Target Level\n");		return -1;	}	if (resp->name == "core_autoidle_res")	if (target_level >= invalidlevelmin &&			target_level <= invalidlevelmax) {		printk(KERN_ERR"Invalid Target Level\n");		return -1;	}	return 0;}int activate_constraint(struct shared_resource *resp,			unsigned short current_value,			unsigned short target_value){	int ind;	unsigned long type = resp->prcm_id;	DPRINTK("CUR_VAL = %d, TAR_VAL = %d\n", current_value, target_value);	if (type == RES_LATENCY_CO) {		switch (target_value) {		case CO_LATENCY_WFI:		/* Allows only wfi + tick suppression. State C1*/		set_acceptable_latency("omap_lt_co", 99);		break;		case CO_LATENCY_MPURET_COREON:		/* Allows upto MPU RET. State C2*/		set_acceptable_latency("omap_lt_co", 3299);		break;		case CO_LATENCY_MPUOFF_COREON:		/* Allows upto MPU OFF. State C3*/		set_acceptable_latency("omap_lt_co", 4999);		break;		case CO_LATENCY_MPUOFF_CORERET:		/* Allows upto CORE RET. State C4*/		set_acceptable_latency("omap_lt_co", 39999);		break;		case CO_UNUSED:		/* Removing the constraints */		remove_acceptable_latency("omap_lt_co");		break;		default:		set_acceptable_latency("omap_lt_co", target_value);		break;		}	} else if ((type == PRCM_ARMFREQ_CONSTRAINT)) {		for (ind = 0; ind < max_vdd1_opp; ind++) {			if (vdd1_arm_dsp_freq[ind][0] >= target_value) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?