1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 /* 3 * SSH packet transport layer. 4 * 5 * Copyright (C) 2019-2020 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 */ 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 int 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 */ 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