aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/include/linux/mei_cl_bus.h
blob: b38a56a13f39277f948c53b8e1a68a4f688d6386 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2013-2016, Intel Corporation. All rights reserved.
 */
#ifndef _LINUX_MEI_CL_BUS_H
#define _LINUX_MEI_CL_BUS_H

#include <linux/device.h>
#include <linux/uuid.h>
#include <linux/mod_devicetable.h>

struct mei_cl_device;
struct mei_device;
struct scatterlist;

typedef void (*mei_cldev_cb_t)(struct mei_cl_device *cldev);

/**
 * struct mei_cl_device - MEI device handle
 * An mei_cl_device pointer is returned from mei_add_device()
 * and links MEI bus clients to their actual ME host client pointer.
 * Drivers for MEI devices will get an mei_cl_device pointer
 * when being probed and shall use it for doing ME bus I/O.
 *
 * @bus_list: device on the bus list
 * @bus: parent mei device
 * @dev: linux driver model device pointer
 * @me_cl: me client
 * @cl: mei client
 * @name: device name
 * @rx_work: async work to execute Rx event callback
 * @rx_cb: Drivers register this callback to get asynchronous ME
 *	Rx buffer pending notifications.
 * @notif_work: async work to execute FW notify event callback
 * @notif_cb: Drivers register this callback to get asynchronous ME
 *	FW notification pending notifications.
 *
 * @do_match: whether the device can be matched with a driver
 * @is_added: device is already scanned
 * @priv_data: client private data
 */
struct mei_cl_device {
	struct list_head bus_list;
	struct mei_device *bus;
	struct device dev;

	struct mei_me_client *me_cl;
	struct mei_cl *cl;
	char name[MEI_CL_NAME_SIZE];

	struct work_struct rx_work;
	mei_cldev_cb_t rx_cb;
	struct work_struct notif_work;
	mei_cldev_cb_t notif_cb;

	unsigned int do_match:1;
	unsigned int is_added:1;

	void *priv_data;
};

#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)

struct mei_cl_driver {
	struct device_driver driver;
	const char *name;

	const struct mei_cl_device_id *id_table;

	int (*probe)(struct mei_cl_device *cldev,
		     const struct mei_cl_device_id *id);
	void (*remove)(struct mei_cl_device *cldev);
};

int __mei_cldev_driver_register(struct mei_cl_driver *cldrv,
				struct module *owner);
#define mei_cldev_driver_register(cldrv)             \
	__mei_cldev_driver_register(cldrv, THIS_MODULE)

void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv);

/**
 * module_mei_cl_driver - Helper macro for registering mei cl driver
 *
 * @__mei_cldrv: mei_cl_driver structure
 *
 *  Helper macro for mei cl drivers which do not do anything special in module
 *  init/exit, for eliminating a boilerplate code.
 */
#define module_mei_cl_driver(__mei_cldrv) \
	module_driver(__mei_cldrv, \
		      mei_cldev_driver_register,\
		      mei_cldev_driver_unregister)

ssize_t mei_cldev_send(struct mei_cl_device *cldev, const u8 *buf,
		       size_t length);
ssize_t mei_cldev_send_timeout(struct mei_cl_device *cldev, const u8 *buf,
			       size_t length, unsigned long timeout);
ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length);
ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
				size_t length);
ssize_t mei_cldev_recv_timeout(struct mei_cl_device *cldev, u8 *buf, size_t length,
			       unsigned long timeout);
ssize_t mei_cldev_send_vtag(struct mei_cl_device *cldev, const u8 *buf,
			    size_t length, u8 vtag);
ssize_t mei_cldev_send_vtag_timeout(struct mei_cl_device *cldev, const u8 *buf,
				    size_t length, u8 vtag, unsigned long timeout);
ssize_t mei_cldev_recv_vtag(struct mei_cl_device *cldev, u8 *buf, size_t length,
			    u8 *vtag);
ssize_t mei_cldev_recv_nonblock_vtag(struct mei_cl_device *cldev, u8 *buf,
				     size_t length, u8 *vtag);
ssize_t mei_cldev_recv_vtag_timeout(struct mei_cl_device *cldev, u8 *buf, size_t length,
			    u8 *vtag, unsigned long timeout);

int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb);
int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
				mei_cldev_cb_t notif_cb);

const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev);
u8 mei_cldev_ver(const struct mei_cl_device *cldev);

void *mei_cldev_get_drvdata(const struct mei_cl_device *cldev);
void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data);

int mei_cldev_enable(struct mei_cl_device *cldev);
int mei_cldev_disable(struct mei_cl_device *cldev);
bool mei_cldev_enabled(const struct mei_cl_device *cldev);
ssize_t mei_cldev_send_gsc_command(struct mei_cl_device *cldev,
				   u8 client_id, u32 fence_id,
				   struct scatterlist *sg_in,
				   size_t total_in_len,
				   struct scatterlist *sg_out);

void *mei_cldev_dma_map(struct mei_cl_device *cldev, u8 buffer_id, size_t size);
int mei_cldev_dma_unmap(struct mei_cl_device *cldev);

#endif /* _LINUX_MEI_CL_BUS_H */