| 1 |
|
| 2 | |
| 3 | * SSH packet transport layer.
|
| 4 | *
|
| 5 | * Copyright (C) 2019-2022 Maximilian Luz <[email protected]>
|
| 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 | 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 |
|
| 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
|