191 lines · c
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_H9#define _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H10 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 is29 * being shut down and should not accept any new packets/data.30 */31enum 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 and39 * the packet's payload data are provided to this function.40 */41struct 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 */77struct 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 139int ssh_ptl_init(struct ssh_ptl *ptl, struct serdev_device *serdev,140 struct ssh_ptl_ops *ops);141 142void 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 builds149 * upon.150 */151static inline struct device *ssh_ptl_get_device(struct ssh_ptl *ptl)152{153 return ptl->serdev ? &ptl->serdev->dev : NULL;154}155 156int ssh_ptl_tx_start(struct ssh_ptl *ptl);157int ssh_ptl_tx_stop(struct ssh_ptl *ptl);158int ssh_ptl_rx_start(struct ssh_ptl *ptl);159int ssh_ptl_rx_stop(struct ssh_ptl *ptl);160void ssh_ptl_shutdown(struct ssh_ptl *ptl);161 162int ssh_ptl_submit(struct ssh_ptl *ptl, struct ssh_packet *p);163void ssh_ptl_cancel(struct ssh_packet *p);164 165ssize_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 for169 * transfer.170 * @ptl: The packet transport layer.171 *172 * Wakes up the packet transmitter thread, notifying it that the underlying173 * transport has more space for data to be transmitted. If the packet174 * transport layer has been shut down, calls to this function will be ignored.175 */176static 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 184void ssh_packet_init(struct ssh_packet *packet, unsigned long type,185 u8 priority, const struct ssh_packet_ops *ops);186 187int ssh_ctrl_packet_cache_init(void);188void ssh_ctrl_packet_cache_destroy(void);189 190#endif /* _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H */191