1c167b9c7SMaximilian Luz /* SPDX-License-Identifier: GPL-2.0+ */
2c167b9c7SMaximilian Luz /*
3c167b9c7SMaximilian Luz  * SSH request transport layer.
4c167b9c7SMaximilian Luz  *
5*221756e6SMaximilian Luz  * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
6c167b9c7SMaximilian Luz  */
7c167b9c7SMaximilian Luz 
8c167b9c7SMaximilian Luz #ifndef _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H
9c167b9c7SMaximilian Luz #define _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H
10c167b9c7SMaximilian Luz 
11c167b9c7SMaximilian Luz #include <linux/atomic.h>
12c167b9c7SMaximilian Luz #include <linux/ktime.h>
13c167b9c7SMaximilian Luz #include <linux/list.h>
14c167b9c7SMaximilian Luz #include <linux/spinlock.h>
15c167b9c7SMaximilian Luz #include <linux/workqueue.h>
16c167b9c7SMaximilian Luz 
17c167b9c7SMaximilian Luz #include <linux/surface_aggregator/serial_hub.h>
18c167b9c7SMaximilian Luz #include <linux/surface_aggregator/controller.h>
19c167b9c7SMaximilian Luz 
20c167b9c7SMaximilian Luz #include "ssh_packet_layer.h"
21c167b9c7SMaximilian Luz 
22c167b9c7SMaximilian Luz /**
23c167b9c7SMaximilian Luz  * enum ssh_rtl_state_flags - State-flags for &struct ssh_rtl.
24c167b9c7SMaximilian Luz  *
25c167b9c7SMaximilian Luz  * @SSH_RTL_SF_SHUTDOWN_BIT:
26c167b9c7SMaximilian Luz  *	Indicates that the request transport layer has been shut down or is
27c167b9c7SMaximilian Luz  *	being shut down and should not accept any new requests.
28c167b9c7SMaximilian Luz  */
29c167b9c7SMaximilian Luz enum ssh_rtl_state_flags {
30c167b9c7SMaximilian Luz 	SSH_RTL_SF_SHUTDOWN_BIT,
31c167b9c7SMaximilian Luz };
32c167b9c7SMaximilian Luz 
33c167b9c7SMaximilian Luz /**
34c167b9c7SMaximilian Luz  * struct ssh_rtl_ops - Callback operations for request transport layer.
35c167b9c7SMaximilian Luz  * @handle_event: Function called when a SSH event has been received. The
36c167b9c7SMaximilian Luz  *                specified function takes the request layer, received command
37c167b9c7SMaximilian Luz  *                struct, and corresponding payload as arguments. If the event
38c167b9c7SMaximilian Luz  *                has no payload, the payload span is empty (not %NULL).
39c167b9c7SMaximilian Luz  */
40c167b9c7SMaximilian Luz struct ssh_rtl_ops {
41c167b9c7SMaximilian Luz 	void (*handle_event)(struct ssh_rtl *rtl, const struct ssh_command *cmd,
42c167b9c7SMaximilian Luz 			     const struct ssam_span *data);
43c167b9c7SMaximilian Luz };
44c167b9c7SMaximilian Luz 
45c167b9c7SMaximilian Luz /**
46c167b9c7SMaximilian Luz  * struct ssh_rtl - SSH request transport layer.
47c167b9c7SMaximilian Luz  * @ptl:           Underlying packet transport layer.
48c167b9c7SMaximilian Luz  * @state:         State(-flags) of the transport layer.
49c167b9c7SMaximilian Luz  * @queue:         Request submission queue.
50c167b9c7SMaximilian Luz  * @queue.lock:    Lock for modifying the request submission queue.
51c167b9c7SMaximilian Luz  * @queue.head:    List-head of the request submission queue.
52c167b9c7SMaximilian Luz  * @pending:       Set/list of pending requests.
53c167b9c7SMaximilian Luz  * @pending.lock:  Lock for modifying the request set.
54c167b9c7SMaximilian Luz  * @pending.head:  List-head of the pending set/list.
55c167b9c7SMaximilian Luz  * @pending.count: Number of currently pending requests.
56c167b9c7SMaximilian Luz  * @tx:            Transmitter subsystem.
57c167b9c7SMaximilian Luz  * @tx.work:       Transmitter work item.
58c167b9c7SMaximilian Luz  * @rtx_timeout:   Retransmission timeout subsystem.
59c167b9c7SMaximilian Luz  * @rtx_timeout.lock:    Lock for modifying the retransmission timeout reaper.
60c167b9c7SMaximilian Luz  * @rtx_timeout.timeout: Timeout interval for retransmission.
61c167b9c7SMaximilian Luz  * @rtx_timeout.expires: Time specifying when the reaper work is next scheduled.
62c167b9c7SMaximilian Luz  * @rtx_timeout.reaper:  Work performing timeout checks and subsequent actions.
63c167b9c7SMaximilian Luz  * @ops:           Request layer operations.
64c167b9c7SMaximilian Luz  */
65c167b9c7SMaximilian Luz struct ssh_rtl {
66c167b9c7SMaximilian Luz 	struct ssh_ptl ptl;
67c167b9c7SMaximilian Luz 	unsigned long state;
68c167b9c7SMaximilian Luz 
69c167b9c7SMaximilian Luz 	struct {
70c167b9c7SMaximilian Luz 		spinlock_t lock;
71c167b9c7SMaximilian Luz 		struct list_head head;
72c167b9c7SMaximilian Luz 	} queue;
73c167b9c7SMaximilian Luz 
74c167b9c7SMaximilian Luz 	struct {
75c167b9c7SMaximilian Luz 		spinlock_t lock;
76c167b9c7SMaximilian Luz 		struct list_head head;
77c167b9c7SMaximilian Luz 		atomic_t count;
78c167b9c7SMaximilian Luz 	} pending;
79c167b9c7SMaximilian Luz 
80c167b9c7SMaximilian Luz 	struct {
81c167b9c7SMaximilian Luz 		struct work_struct work;
82c167b9c7SMaximilian Luz 	} tx;
83c167b9c7SMaximilian Luz 
84c167b9c7SMaximilian Luz 	struct {
85c167b9c7SMaximilian Luz 		spinlock_t lock;
86c167b9c7SMaximilian Luz 		ktime_t timeout;
87c167b9c7SMaximilian Luz 		ktime_t expires;
88c167b9c7SMaximilian Luz 		struct delayed_work reaper;
89c167b9c7SMaximilian Luz 	} rtx_timeout;
90c167b9c7SMaximilian Luz 
91c167b9c7SMaximilian Luz 	struct ssh_rtl_ops ops;
92c167b9c7SMaximilian Luz };
93c167b9c7SMaximilian Luz 
94c167b9c7SMaximilian Luz #define rtl_dbg(r, fmt, ...)  ptl_dbg(&(r)->ptl, fmt, ##__VA_ARGS__)
95c167b9c7SMaximilian Luz #define rtl_info(p, fmt, ...) ptl_info(&(p)->ptl, fmt, ##__VA_ARGS__)
96c167b9c7SMaximilian Luz #define rtl_warn(r, fmt, ...) ptl_warn(&(r)->ptl, fmt, ##__VA_ARGS__)
97c167b9c7SMaximilian Luz #define rtl_err(r, fmt, ...)  ptl_err(&(r)->ptl, fmt, ##__VA_ARGS__)
98c167b9c7SMaximilian Luz #define rtl_dbg_cond(r, fmt, ...) __ssam_prcond(rtl_dbg, r, fmt, ##__VA_ARGS__)
99c167b9c7SMaximilian Luz 
100c167b9c7SMaximilian Luz #define to_ssh_rtl(ptr, member) \
101c167b9c7SMaximilian Luz 	container_of(ptr, struct ssh_rtl, member)
102c167b9c7SMaximilian Luz 
103c167b9c7SMaximilian Luz /**
104c167b9c7SMaximilian Luz  * ssh_rtl_get_device() - Get device associated with request transport layer.
105c167b9c7SMaximilian Luz  * @rtl: The request transport layer.
106c167b9c7SMaximilian Luz  *
107c167b9c7SMaximilian Luz  * Return: Returns the device on which the given request transport layer
108c167b9c7SMaximilian Luz  * builds upon.
109c167b9c7SMaximilian Luz  */
ssh_rtl_get_device(struct ssh_rtl * rtl)110c167b9c7SMaximilian Luz static inline struct device *ssh_rtl_get_device(struct ssh_rtl *rtl)
111c167b9c7SMaximilian Luz {
112c167b9c7SMaximilian Luz 	return ssh_ptl_get_device(&rtl->ptl);
113c167b9c7SMaximilian Luz }
114c167b9c7SMaximilian Luz 
115c167b9c7SMaximilian Luz /**
116c167b9c7SMaximilian Luz  * ssh_request_rtl() - Get request transport layer associated with request.
117c167b9c7SMaximilian Luz  * @rqst: The request to get the request transport layer reference for.
118c167b9c7SMaximilian Luz  *
119c167b9c7SMaximilian Luz  * Return: Returns the &struct ssh_rtl associated with the given SSH request.
120c167b9c7SMaximilian Luz  */
ssh_request_rtl(struct ssh_request * rqst)121c167b9c7SMaximilian Luz static inline struct ssh_rtl *ssh_request_rtl(struct ssh_request *rqst)
122c167b9c7SMaximilian Luz {
123c167b9c7SMaximilian Luz 	struct ssh_ptl *ptl;
124c167b9c7SMaximilian Luz 
125c167b9c7SMaximilian Luz 	ptl = READ_ONCE(rqst->packet.ptl);
126c167b9c7SMaximilian Luz 	return likely(ptl) ? to_ssh_rtl(ptl, ptl) : NULL;
127c167b9c7SMaximilian Luz }
128c167b9c7SMaximilian Luz 
129c167b9c7SMaximilian Luz int ssh_rtl_submit(struct ssh_rtl *rtl, struct ssh_request *rqst);
130c167b9c7SMaximilian Luz bool ssh_rtl_cancel(struct ssh_request *rqst, bool pending);
131c167b9c7SMaximilian Luz 
132c167b9c7SMaximilian Luz int ssh_rtl_init(struct ssh_rtl *rtl, struct serdev_device *serdev,
133c167b9c7SMaximilian Luz 		 const struct ssh_rtl_ops *ops);
134c167b9c7SMaximilian Luz 
135c167b9c7SMaximilian Luz int ssh_rtl_start(struct ssh_rtl *rtl);
136c167b9c7SMaximilian Luz int ssh_rtl_flush(struct ssh_rtl *rtl, unsigned long timeout);
137c167b9c7SMaximilian Luz void ssh_rtl_shutdown(struct ssh_rtl *rtl);
138c167b9c7SMaximilian Luz void ssh_rtl_destroy(struct ssh_rtl *rtl);
139c167b9c7SMaximilian Luz 
140c167b9c7SMaximilian Luz int ssh_request_init(struct ssh_request *rqst, enum ssam_request_flags flags,
141c167b9c7SMaximilian Luz 		     const struct ssh_request_ops *ops);
142c167b9c7SMaximilian Luz 
143c167b9c7SMaximilian Luz #endif /* _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H */
144