drivers/soc/xilinx/xlnx_event_manager.c

Source file repositories/reference/linux-study-clean/drivers/soc/xilinx/xlnx_event_manager.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/xilinx/xlnx_event_manager.c
Extension
.c
Size
20124 bytes
Lines
721
Domain
Driver Families
Bucket
drivers/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct agent_cb {
	void *agent_data;
	event_cb_func_t eve_cb;
	struct list_head list;
};

/**
 * struct registered_event_data - Registered Event Data.
 * @key:		key is the combine id(Node-Id | Event-Id) of type u64
 *			where upper u32 for Node-Id and lower u32 for Event-Id,
 *			And this used as key to index into hashmap.
 * @cb_type:		Type of Api callback, like PM_NOTIFY_CB, etc.
 * @wake:		If this flag set, firmware will wake up processor if is
 *			in sleep or power down state.
 * @cb_list_head:	Head of call back data list which contain the information
 *			about registered handler and private data.
 * @hentry:		hlist_node that hooks this entry into hashtable.
 */
struct registered_event_data {
	u64 key;
	enum pm_api_cb_id cb_type;
	bool wake;
	struct list_head cb_list_head;
	struct hlist_node hentry;
};

static bool xlnx_is_error_event(const u32 node_id)
{
	u32 pm_family_code;

	zynqmp_pm_get_family_info(&pm_family_code);

	if (pm_family_code == PM_VERSAL_FAMILY_CODE) {
		if (node_id == VERSAL_EVENT_ERROR_PMC_ERR1 ||
		    node_id == VERSAL_EVENT_ERROR_PMC_ERR2 ||
		    node_id == VERSAL_EVENT_ERROR_PSM_ERR1 ||
		    node_id == VERSAL_EVENT_ERROR_PSM_ERR2)
			return true;
	} else if (pm_family_code == PM_VERSAL_NET_FAMILY_CODE) {
		if (node_id == VERSAL_NET_EVENT_ERROR_PMC_ERR1 ||
		    node_id == VERSAL_NET_EVENT_ERROR_PMC_ERR2 ||
		    node_id == VERSAL_NET_EVENT_ERROR_PMC_ERR3 ||
		    node_id == VERSAL_NET_EVENT_ERROR_PSM_ERR1 ||
		    node_id == VERSAL_NET_EVENT_ERROR_PSM_ERR2 ||
		    node_id == VERSAL_NET_EVENT_ERROR_PSM_ERR3 ||
		    node_id == VERSAL_NET_EVENT_ERROR_PSM_ERR4)
			return true;
	}

	return false;
}

static int xlnx_add_cb_for_notify_event(const u32 node_id, const u32 event, const bool wake,
					event_cb_func_t cb_fun,	void *data)
{
	u64 key = 0;
	bool present_in_hash = false;
	struct registered_event_data *eve_data;
	struct agent_cb *cb_data;
	struct agent_cb *cb_pos;
	struct agent_cb *cb_next;

	key = ((u64)node_id << 32U) | (u64)event;
	/* Check for existing entry in hash table for given key id */
	hash_for_each_possible(reg_driver_map, eve_data, hentry, key) {
		if (eve_data->key == key) {
			present_in_hash = true;
			break;
		}
	}

	if (!present_in_hash) {
		/* Add new entry if not present in HASH table */
		eve_data = kmalloc_obj(*eve_data);
		if (!eve_data)
			return -ENOMEM;
		eve_data->key = key;
		eve_data->cb_type = PM_NOTIFY_CB;
		eve_data->wake = wake;
		INIT_LIST_HEAD(&eve_data->cb_list_head);

		cb_data = kmalloc_obj(*cb_data);
		if (!cb_data) {
			kfree(eve_data);
			return -ENOMEM;
		}
		cb_data->eve_cb = cb_fun;
		cb_data->agent_data = data;

		/* Add into callback list */

Annotation

Implementation Notes