xref: /linux/drivers/thunderbolt/ctl.h (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2f25bf6fcSAndreas Noever /*
315c6784cSMika Westerberg  * Thunderbolt driver - control channel and configuration commands
4f25bf6fcSAndreas Noever  *
5f25bf6fcSAndreas Noever  * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
615c6784cSMika Westerberg  * Copyright (C) 2018, Intel Corporation
7f25bf6fcSAndreas Noever  */
8f25bf6fcSAndreas Noever 
9f25bf6fcSAndreas Noever #ifndef _TB_CFG
10f25bf6fcSAndreas Noever #define _TB_CFG
11f25bf6fcSAndreas Noever 
12d7f781bfSMika Westerberg #include <linux/kref.h>
13eaf8ff35SMika Westerberg #include <linux/thunderbolt.h>
14d7f781bfSMika Westerberg 
15f25bf6fcSAndreas Noever #include "nhi.h"
1632af9434SMika Westerberg #include "tb_msgs.h"
17f25bf6fcSAndreas Noever 
18f25bf6fcSAndreas Noever /* control channel */
19f25bf6fcSAndreas Noever struct tb_ctl;
20f25bf6fcSAndreas Noever 
21d1ff7024SMika Westerberg typedef bool (*event_cb)(void *data, enum tb_cfg_pkg_type type,
2281a54b5eSMika Westerberg 			 const void *buf, size_t size);
23f25bf6fcSAndreas Noever 
24*a0c45b0bSGil Fine struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, int index, int timeout_msec,
25*a0c45b0bSGil Fine 			    event_cb cb, void *cb_data);
26f25bf6fcSAndreas Noever void tb_ctl_start(struct tb_ctl *ctl);
27f25bf6fcSAndreas Noever void tb_ctl_stop(struct tb_ctl *ctl);
28f25bf6fcSAndreas Noever void tb_ctl_free(struct tb_ctl *ctl);
29f25bf6fcSAndreas Noever 
30f25bf6fcSAndreas Noever /* configuration commands */
31f25bf6fcSAndreas Noever 
32f25bf6fcSAndreas Noever struct tb_cfg_result {
33f25bf6fcSAndreas Noever 	u64 response_route;
34f25bf6fcSAndreas Noever 	u32 response_port; /*
35f25bf6fcSAndreas Noever 			    * If err = 1 then this is the port that send the
36f25bf6fcSAndreas Noever 			    * error.
37f25bf6fcSAndreas Noever 			    * If err = 0 and if this was a cfg_read/write then
3834b9715bSXiang Wangx 			    * this is the upstream port of the responding
39f25bf6fcSAndreas Noever 			    * switch.
40f25bf6fcSAndreas Noever 			    * Otherwise the field is set to zero.
41f25bf6fcSAndreas Noever 			    */
42f25bf6fcSAndreas Noever 	int err; /* negative errors, 0 for success, 1 for tb errors */
43f25bf6fcSAndreas Noever 	enum tb_cfg_error tb_error; /* valid if err == 1 */
44f25bf6fcSAndreas Noever };
45f25bf6fcSAndreas Noever 
46d7f781bfSMika Westerberg struct ctl_pkg {
47d7f781bfSMika Westerberg 	struct tb_ctl *ctl;
48d7f781bfSMika Westerberg 	void *buffer;
49d7f781bfSMika Westerberg 	struct ring_frame frame;
50d7f781bfSMika Westerberg };
51d7f781bfSMika Westerberg 
52d7f781bfSMika Westerberg /**
53d7f781bfSMika Westerberg  * struct tb_cfg_request - Control channel request
54d7f781bfSMika Westerberg  * @kref: Reference count
55d7f781bfSMika Westerberg  * @ctl: Pointer to the control channel structure. Only set when the
56d7f781bfSMika Westerberg  *	 request is queued.
57d7f781bfSMika Westerberg  * @request_size: Size of the request packet (in bytes)
58d7f781bfSMika Westerberg  * @request_type: Type of the request packet
59d7f781bfSMika Westerberg  * @response: Response is stored here
60d7f781bfSMika Westerberg  * @response_size: Maximum size of one response packet
61d7f781bfSMika Westerberg  * @response_type: Expected type of the response packet
62d7f781bfSMika Westerberg  * @npackets: Number of packets expected to be returned with this request
63d7f781bfSMika Westerberg  * @match: Function used to match the incoming packet
64d7f781bfSMika Westerberg  * @copy: Function used to copy the incoming packet to @response
65d7f781bfSMika Westerberg  * @callback: Callback called when the request is finished successfully
66d7f781bfSMika Westerberg  * @callback_data: Data to be passed to @callback
67d7f781bfSMika Westerberg  * @flags: Flags for the request
68d7f781bfSMika Westerberg  * @work: Work item used to complete the request
69d7f781bfSMika Westerberg  * @result: Result after the request has been completed
70d7f781bfSMika Westerberg  * @list: Requests are queued using this field
71d7f781bfSMika Westerberg  *
72d7f781bfSMika Westerberg  * An arbitrary request over Thunderbolt control channel. For standard
73d7f781bfSMika Westerberg  * control channel message, one should use tb_cfg_read/write() and
74d7f781bfSMika Westerberg  * friends if possible.
75d7f781bfSMika Westerberg  */
76d7f781bfSMika Westerberg struct tb_cfg_request {
77d7f781bfSMika Westerberg 	struct kref kref;
78d7f781bfSMika Westerberg 	struct tb_ctl *ctl;
79d7f781bfSMika Westerberg 	const void *request;
80d7f781bfSMika Westerberg 	size_t request_size;
81d7f781bfSMika Westerberg 	enum tb_cfg_pkg_type request_type;
82d7f781bfSMika Westerberg 	void *response;
83d7f781bfSMika Westerberg 	size_t response_size;
84d7f781bfSMika Westerberg 	enum tb_cfg_pkg_type response_type;
85d7f781bfSMika Westerberg 	size_t npackets;
86d7f781bfSMika Westerberg 	bool (*match)(const struct tb_cfg_request *req,
87d7f781bfSMika Westerberg 		      const struct ctl_pkg *pkg);
88d7f781bfSMika Westerberg 	bool (*copy)(struct tb_cfg_request *req, const struct ctl_pkg *pkg);
89d7f781bfSMika Westerberg 	void (*callback)(void *callback_data);
90d7f781bfSMika Westerberg 	void *callback_data;
91d7f781bfSMika Westerberg 	unsigned long flags;
92d7f781bfSMika Westerberg 	struct work_struct work;
93d7f781bfSMika Westerberg 	struct tb_cfg_result result;
94d7f781bfSMika Westerberg 	struct list_head list;
95d7f781bfSMika Westerberg };
96d7f781bfSMika Westerberg 
97d7f781bfSMika Westerberg #define TB_CFG_REQUEST_ACTIVE		0
98d7f781bfSMika Westerberg #define TB_CFG_REQUEST_CANCELED		1
99d7f781bfSMika Westerberg 
100d7f781bfSMika Westerberg struct tb_cfg_request *tb_cfg_request_alloc(void);
101d7f781bfSMika Westerberg void tb_cfg_request_get(struct tb_cfg_request *req);
102d7f781bfSMika Westerberg void tb_cfg_request_put(struct tb_cfg_request *req);
103d7f781bfSMika Westerberg int tb_cfg_request(struct tb_ctl *ctl, struct tb_cfg_request *req,
104d7f781bfSMika Westerberg 		   void (*callback)(void *), void *callback_data);
105d7f781bfSMika Westerberg void tb_cfg_request_cancel(struct tb_cfg_request *req, int err);
106d7f781bfSMika Westerberg struct tb_cfg_result tb_cfg_request_sync(struct tb_ctl *ctl,
107d7f781bfSMika Westerberg 			struct tb_cfg_request *req, int timeout_msec);
108d7f781bfSMika Westerberg 
tb_cfg_get_route(const struct tb_cfg_header * header)109ac6c44deSMika Westerberg static inline u64 tb_cfg_get_route(const struct tb_cfg_header *header)
110ac6c44deSMika Westerberg {
111ac6c44deSMika Westerberg 	return (u64) header->route_hi << 32 | header->route_lo;
112ac6c44deSMika Westerberg }
113f25bf6fcSAndreas Noever 
tb_cfg_make_header(u64 route)11405c242e9SMika Westerberg static inline struct tb_cfg_header tb_cfg_make_header(u64 route)
11505c242e9SMika Westerberg {
11605c242e9SMika Westerberg 	struct tb_cfg_header header = {
11705c242e9SMika Westerberg 		.route_hi = route >> 32,
11805c242e9SMika Westerberg 		.route_lo = route,
11905c242e9SMika Westerberg 	};
12005c242e9SMika Westerberg 	/* check for overflow, route_hi is not 32 bits! */
12105c242e9SMika Westerberg 	WARN_ON(tb_cfg_get_route(&header) != route);
12205c242e9SMika Westerberg 	return header;
12305c242e9SMika Westerberg }
12405c242e9SMika Westerberg 
1256ce35635SMika Westerberg int tb_cfg_ack_notification(struct tb_ctl *ctl, u64 route,
1266ce35635SMika Westerberg 			    const struct cfg_error_pkg *error);
127210e9f56SMika Westerberg int tb_cfg_ack_plug(struct tb_ctl *ctl, u64 route, u32 port, bool unplug);
128bda83aecSMika Westerberg struct tb_cfg_result tb_cfg_reset(struct tb_ctl *ctl, u64 route);
129f25bf6fcSAndreas Noever struct tb_cfg_result tb_cfg_read_raw(struct tb_ctl *ctl, void *buffer,
130f25bf6fcSAndreas Noever 				     u64 route, u32 port,
131f25bf6fcSAndreas Noever 				     enum tb_cfg_space space, u32 offset,
132f25bf6fcSAndreas Noever 				     u32 length, int timeout_msec);
13316a1258aSMika Westerberg struct tb_cfg_result tb_cfg_write_raw(struct tb_ctl *ctl, const void *buffer,
134f25bf6fcSAndreas Noever 				      u64 route, u32 port,
135f25bf6fcSAndreas Noever 				      enum tb_cfg_space space, u32 offset,
136f25bf6fcSAndreas Noever 				      u32 length, int timeout_msec);
137f25bf6fcSAndreas Noever int tb_cfg_read(struct tb_ctl *ctl, void *buffer, u64 route, u32 port,
138f25bf6fcSAndreas Noever 		enum tb_cfg_space space, u32 offset, u32 length);
13916a1258aSMika Westerberg int tb_cfg_write(struct tb_ctl *ctl, const void *buffer, u64 route, u32 port,
140f25bf6fcSAndreas Noever 		 enum tb_cfg_space space, u32 offset, u32 length);
141f25bf6fcSAndreas Noever int tb_cfg_get_upstream_port(struct tb_ctl *ctl, u64 route);
142f25bf6fcSAndreas Noever 
143f25bf6fcSAndreas Noever 
144f25bf6fcSAndreas Noever #endif
145