Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0+ */
0002 /*
0003  * SSH packet transport layer.
0004  *
0005  * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
0006  */
0007 
0008 #ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
0009 #define _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
0010 
0011 #include <linux/atomic.h>
0012 #include <linux/kfifo.h>
0013 #include <linux/ktime.h>
0014 #include <linux/list.h>
0015 #include <linux/serdev.h>
0016 #include <linux/spinlock.h>
0017 #include <linux/types.h>
0018 #include <linux/wait.h>
0019 #include <linux/workqueue.h>
0020 
0021 #include <linux/surface_aggregator/serial_hub.h>
0022 #include "ssh_parser.h"
0023 
0024 /**
0025  * enum ssh_ptl_state_flags - State-flags for &struct ssh_ptl.
0026  *
0027  * @SSH_PTL_SF_SHUTDOWN_BIT:
0028  *  Indicates that the packet transport layer has been shut down or is
0029  *  being shut down and should not accept any new packets/data.
0030  */
0031 enum ssh_ptl_state_flags {
0032     SSH_PTL_SF_SHUTDOWN_BIT,
0033 };
0034 
0035 /**
0036  * struct ssh_ptl_ops - Callback operations for packet transport layer.
0037  * @data_received: Function called when a data-packet has been received. Both,
0038  *                 the packet layer on which the packet has been received and
0039  *                 the packet's payload data are provided to this function.
0040  */
0041 struct ssh_ptl_ops {
0042     void (*data_received)(struct ssh_ptl *p, const struct ssam_span *data);
0043 };
0044 
0045 /**
0046  * struct ssh_ptl - SSH packet transport layer.
0047  * @serdev:        Serial device providing the underlying data transport.
0048  * @state:         State(-flags) of the transport layer.
0049  * @queue:         Packet submission queue.
0050  * @queue.lock:    Lock for modifying the packet submission queue.
0051  * @queue.head:    List-head of the packet submission queue.
0052  * @pending:       Set/list of pending packets.
0053  * @pending.lock:  Lock for modifying the pending set.
0054  * @pending.head:  List-head of the pending set/list.
0055  * @pending.count: Number of currently pending packets.
0056  * @tx:            Transmitter subsystem.
0057  * @tx.running:    Flag indicating (desired) transmitter thread state.
0058  * @tx.thread:     Transmitter thread.
0059  * @tx.thread_cplt_tx:  Completion for transmitter thread waiting on transfer.
0060  * @tx.thread_cplt_pkt: Completion for transmitter thread waiting on packets.
0061  * @tx.packet_wq:  Waitqueue-head for packet transmit completion.
0062  * @rx:            Receiver subsystem.
0063  * @rx.thread:     Receiver thread.
0064  * @rx.wq:         Waitqueue-head for receiver thread.
0065  * @rx.fifo:       Buffer for receiving data/pushing data to receiver thread.
0066  * @rx.buf:        Buffer for evaluating data on receiver thread.
0067  * @rx.blocked:    List of recent/blocked sequence IDs to detect retransmission.
0068  * @rx.blocked.seqs:   Array of blocked sequence IDs.
0069  * @rx.blocked.offset: Offset indicating where a new ID should be inserted.
0070  * @rtx_timeout:   Retransmission timeout subsystem.
0071  * @rtx_timeout.lock:    Lock for modifying the retransmission timeout reaper.
0072  * @rtx_timeout.timeout: Timeout interval for retransmission.
0073  * @rtx_timeout.expires: Time specifying when the reaper work is next scheduled.
0074  * @rtx_timeout.reaper:  Work performing timeout checks and subsequent actions.
0075  * @ops:           Packet layer operations.
0076  */
0077 struct ssh_ptl {
0078     struct serdev_device *serdev;
0079     unsigned long state;
0080 
0081     struct {
0082         spinlock_t lock;
0083         struct list_head head;
0084     } queue;
0085 
0086     struct {
0087         spinlock_t lock;
0088         struct list_head head;
0089         atomic_t count;
0090     } pending;
0091 
0092     struct {
0093         atomic_t running;
0094         struct task_struct *thread;
0095         struct completion thread_cplt_tx;
0096         struct completion thread_cplt_pkt;
0097         struct wait_queue_head packet_wq;
0098     } tx;
0099 
0100     struct {
0101         struct task_struct *thread;
0102         struct wait_queue_head wq;
0103         struct kfifo fifo;
0104         struct sshp_buf buf;
0105 
0106         struct {
0107             u16 seqs[8];
0108             u16 offset;
0109         } blocked;
0110     } rx;
0111 
0112     struct {
0113         spinlock_t lock;
0114         ktime_t timeout;
0115         ktime_t expires;
0116         struct delayed_work reaper;
0117     } rtx_timeout;
0118 
0119     struct ssh_ptl_ops ops;
0120 };
0121 
0122 #define __ssam_prcond(func, p, fmt, ...)        \
0123     do {                        \
0124         typeof(p) __p = (p);            \
0125                             \
0126         if (__p)                \
0127             func(__p, fmt, ##__VA_ARGS__);  \
0128     } while (0)
0129 
0130 #define ptl_dbg(p, fmt, ...)  dev_dbg(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
0131 #define ptl_info(p, fmt, ...) dev_info(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
0132 #define ptl_warn(p, fmt, ...) dev_warn(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
0133 #define ptl_err(p, fmt, ...)  dev_err(&(p)->serdev->dev, fmt, ##__VA_ARGS__)
0134 #define ptl_dbg_cond(p, fmt, ...) __ssam_prcond(ptl_dbg, p, fmt, ##__VA_ARGS__)
0135 
0136 #define to_ssh_ptl(ptr, member) \
0137     container_of(ptr, struct ssh_ptl, member)
0138 
0139 int ssh_ptl_init(struct ssh_ptl *ptl, struct serdev_device *serdev,
0140          struct ssh_ptl_ops *ops);
0141 
0142 void ssh_ptl_destroy(struct ssh_ptl *ptl);
0143 
0144 /**
0145  * ssh_ptl_get_device() - Get device associated with packet transport layer.
0146  * @ptl: The packet transport layer.
0147  *
0148  * Return: Returns the device on which the given packet transport layer builds
0149  * upon.
0150  */
0151 static inline struct device *ssh_ptl_get_device(struct ssh_ptl *ptl)
0152 {
0153     return ptl->serdev ? &ptl->serdev->dev : NULL;
0154 }
0155 
0156 int ssh_ptl_tx_start(struct ssh_ptl *ptl);
0157 int ssh_ptl_tx_stop(struct ssh_ptl *ptl);
0158 int ssh_ptl_rx_start(struct ssh_ptl *ptl);
0159 int ssh_ptl_rx_stop(struct ssh_ptl *ptl);
0160 void ssh_ptl_shutdown(struct ssh_ptl *ptl);
0161 
0162 int ssh_ptl_submit(struct ssh_ptl *ptl, struct ssh_packet *p);
0163 void ssh_ptl_cancel(struct ssh_packet *p);
0164 
0165 int ssh_ptl_rx_rcvbuf(struct ssh_ptl *ptl, const u8 *buf, size_t n);
0166 
0167 /**
0168  * ssh_ptl_tx_wakeup_transfer() - Wake up packet transmitter thread for
0169  * transfer.
0170  * @ptl: The packet transport layer.
0171  *
0172  * Wakes up the packet transmitter thread, notifying it that the underlying
0173  * transport has more space for data to be transmitted. If the packet
0174  * transport layer has been shut down, calls to this function will be ignored.
0175  */
0176 static inline void ssh_ptl_tx_wakeup_transfer(struct ssh_ptl *ptl)
0177 {
0178     if (test_bit(SSH_PTL_SF_SHUTDOWN_BIT, &ptl->state))
0179         return;
0180 
0181     complete(&ptl->tx.thread_cplt_tx);
0182 }
0183 
0184 void ssh_packet_init(struct ssh_packet *packet, unsigned long type,
0185              u8 priority, const struct ssh_packet_ops *ops);
0186 
0187 int ssh_ctrl_packet_cache_init(void);
0188 void ssh_ctrl_packet_cache_destroy(void);
0189 
0190 #endif /* _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H */