1  /* SPDX-License-Identifier: GPL-2.0+ */
2  /*
3   * SSH packet transport layer.
4   *
5   * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
6   */
7  
8  #ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
9  #define _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
10  
11  #include <linux/atomic.h>
12  #include <linux/kfifo.h>
13  #include <linux/ktime.h>
14  #include <linux/list.h>
15  #include <linux/serdev.h>
16  #include <linux/spinlock.h>
17  #include <linux/types.h>
18  #include <linux/wait.h>
19  #include <linux/workqueue.h>
20  
21  #include <linux/surface_aggregator/serial_hub.h>
22  #include "ssh_parser.h"
23  
24  /**
25   * enum ssh_ptl_state_flags - State-flags for &struct ssh_ptl.
26   *
27   * @SSH_PTL_SF_SHUTDOWN_BIT:
28   *	Indicates that the packet transport layer has been shut down or is
29   *	being shut down and should not accept any new packets/data.
30   */
31  enum ssh_ptl_state_flags {
32  	SSH_PTL_SF_SHUTDOWN_BIT,
33  };
34  
35  /**
36   * struct ssh_ptl_ops - Callback operations for packet transport layer.
37   * @data_received: Function called when a data-packet has been received. Both,
38   *                 the packet layer on which the packet has been received and
39   *                 the packet's payload data are provided to this function.
40   */
41  struct ssh_ptl_ops {
42  	void (*data_received)(struct ssh_ptl *p, const struct ssam_span *data);
43  };
44  
45  /**
46   * struct ssh_ptl - SSH packet transport layer.
47   * @serdev:        Serial device providing the underlying data transport.
48   * @state:         State(-flags) of the transport layer.
49   * @queue:         Packet submission queue.
50   * @queue.lock:    Lock for modifying the packet submission queue.
51   * @queue.head:    List-head of the packet submission queue.
52   * @pending:       Set/list of pending packets.
53   * @pending.lock:  Lock for modifying the pending set.
54   * @pending.head:  List-head of the pending set/list.
55   * @pending.count: Number of currently pending packets.
56   * @tx:            Transmitter subsystem.
57   * @tx.running:    Flag indicating (desired) transmitter thread state.
58   * @tx.thread:     Transmitter thread.
59   * @tx.thread_cplt_tx:  Completion for transmitter thread waiting on transfer.
60   * @tx.thread_cplt_pkt: Completion for transmitter thread waiting on packets.
61   * @tx.packet_wq:  Waitqueue-head for packet transmit completion.
62   * @rx:            Receiver subsystem.
63   * @rx.thread:     Receiver thread.
64   * @rx.wq:         Waitqueue-head for receiver thread.
65   * @rx.fifo:       Buffer for receiving data/pushing data to receiver thread.
66   * @rx.buf:        Buffer for evaluating data on receiver thread.
67   * @rx.blocked:    List of recent/blocked sequence IDs to detect retransmission.
68   * @rx.blocked.seqs:   Array of blocked sequence IDs.
69   * @rx.blocked.offset: Offset indicating where a new ID should be inserted.
70   * @rtx_timeout:   Retransmission timeout subsystem.
71   * @rtx_timeout.lock:    Lock for modifying the retransmission timeout reaper.
72   * @rtx_timeout.timeout: Timeout interval for retransmission.
73   * @rtx_timeout.expires: Time specifying when the reaper work is next scheduled.
74   * @rtx_timeout.reaper:  Work performing timeout checks and subsequent actions.
75   * @ops:           Packet layer operations.
76   */
77  struct ssh_ptl {
78  	struct serdev_device *serdev;
79  	unsigned long state;
80  
81  	struct {
82  		spinlock_t lock;
83  		struct list_head head;
84  	} queue;
85  
86  	struct {
87  		spinlock_t lock;
88  		struct list_head head;
89  		atomic_t count;
90  	} pending;
91  
92  	struct {
93  		atomic_t running;
94  		struct task_struct *thread;
95  		struct completion thread_cplt_tx;
96  		struct completion thread_cplt_pkt;
97  		struct wait_queue_head packet_wq;
98  	} tx;
99  
100  	struct {
101  		struct task_struct *thread;
102  		struct wait_queue_head wq;
103  		struct kfifo fifo;
104  		struct sshp_buf buf;
105  
106  		struct {
107  			u16 seqs[8];
108  			u16 offset;
109  		} blocked;
110  	} rx;
111  
112  	struct {
113  		spinlock_t lock;
114  		ktime_t timeout;
115  		ktime_t expires;
116  		struct delayed_work reaper;
117  	} rtx_timeout;
118  
119  	struct ssh_ptl_ops ops;
120  };
121  
122  #define __ssam_prcond(func, p, fmt, ...)		\
123  	do {						\
124  		typeof(p) __p = (p);			\
125  							\
126  		if (__p)				\
127  			func(__p, fmt, ##__VA_ARGS__);	\
128  	} while (0)
129  
130  #define ptl_dbg(p, fmt, ...)  dev_dbg(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
131  #define ptl_info(p, fmt, ...) dev_info(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
132  #define ptl_warn(p, fmt, ...) dev_warn(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
133  #define ptl_err(p, fmt, ...)  dev_err(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
134  #define ptl_dbg_cond(p, fmt, ...) __ssam_prcond(ptl_dbg, p, fmt, ##__VA_ARGS__)
135  
136  #define to_ssh_ptl(ptr, member) \
137  	container_of(ptr, struct ssh_ptl, member)
138  
139  int ssh_ptl_init(struct ssh_ptl *ptl, struct serdev_device *serdev,
140  		 struct ssh_ptl_ops *ops);
141  
142  void ssh_ptl_destroy(struct ssh_ptl *ptl);
143  
144  /**
145   * ssh_ptl_get_device() - Get device associated with packet transport layer.
146   * @ptl: The packet transport layer.
147   *
148   * Return: Returns the device on which the given packet transport layer builds
149   * upon.
150   */
ssh_ptl_get_device(struct ssh_ptl * ptl)151  static inline struct device *ssh_ptl_get_device(struct ssh_ptl *ptl)
152  {
153  	return ptl->serdev ? &ptl->serdev->dev : NULL;
154  }
155  
156  int ssh_ptl_tx_start(struct ssh_ptl *ptl);
157  int ssh_ptl_tx_stop(struct ssh_ptl *ptl);
158  int ssh_ptl_rx_start(struct ssh_ptl *ptl);
159  int ssh_ptl_rx_stop(struct ssh_ptl *ptl);
160  void ssh_ptl_shutdown(struct ssh_ptl *ptl);
161  
162  int ssh_ptl_submit(struct ssh_ptl *ptl, struct ssh_packet *p);
163  void ssh_ptl_cancel(struct ssh_packet *p);
164  
165  ssize_t ssh_ptl_rx_rcvbuf(struct ssh_ptl *ptl, const u8 *buf, size_t n);
166  
167  /**
168   * ssh_ptl_tx_wakeup_transfer() - Wake up packet transmitter thread for
169   * transfer.
170   * @ptl: The packet transport layer.
171   *
172   * Wakes up the packet transmitter thread, notifying it that the underlying
173   * transport has more space for data to be transmitted. If the packet
174   * transport layer has been shut down, calls to this function will be ignored.
175   */
ssh_ptl_tx_wakeup_transfer(struct ssh_ptl * ptl)176  static inline void ssh_ptl_tx_wakeup_transfer(struct ssh_ptl *ptl)
177  {
178  	if (test_bit(SSH_PTL_SF_SHUTDOWN_BIT, &ptl->state))
179  		return;
180  
181  	complete(&ptl->tx.thread_cplt_tx);
182  }
183  
184  void ssh_packet_init(struct ssh_packet *packet, unsigned long type,
185  		     u8 priority, const struct ssh_packet_ops *ops);
186  
187  int ssh_ctrl_packet_cache_init(void);
188  void ssh_ctrl_packet_cache_destroy(void);
189  
190  #endif /* _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H */
191