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