#ifndef __T4_TOM_H__
#define __T4_TOM_H__
#include <sys/vmem.h>
#include "common/t4_hw.h"
#include "common/t4_msg.h"
#include "tom/t4_tls.h"
#define LISTEN_HASH_SIZE 32
#define MIN_RCV_WND (24 * 1024U)
#define MAX_RCV_WND ((1U << 27) - 1)
#define DDP_RSVD_WIN (16 * 1024U)
#define SB_DDP_INDICATE SB_IN_TOE
#define USE_DDP_RX_FLOW_CONTROL
#define PPOD_SZ(n) ((n) * sizeof(struct pagepod))
#define PPOD_SIZE (PPOD_SZ(1))
enum {
TPF_ATTACHED = (1 << 0),
TPF_FLOWC_WR_SENT = (1 << 1),
TPF_TX_DATA_SENT = (1 << 2),
TPF_TX_SUSPENDED = (1 << 3),
TPF_SEND_FIN = (1 << 4),
TPF_FIN_SENT = (1 << 5),
TPF_ABORT_SHUTDOWN = (1 << 6),
TPF_CPL_PENDING = (1 << 7),
TPF_SYNQE = (1 << 8),
TPF_SYNQE_EXPANDED = (1 << 9),
TPF_TLS_STARTING = (1 << 10),
TPF_KTLS = (1 << 11),
TPF_INITIALIZED = (1 << 12),
TPF_TLS_RECEIVE = (1 << 13),
TPF_TLS_RX_QUIESCING = (1 << 14),
TPF_TLS_RX_QUIESCED = (1 << 15),
TPF_WAITING_FOR_FINAL = (1<< 16),
TPF_IN_TOEP_LIST = (1 << 17),
};
enum {
DDP_OK = (1 << 0),
DDP_SC_REQ = (1 << 1),
DDP_ON = (1 << 2),
DDP_BUF0_ACTIVE = (1 << 3),
DDP_BUF1_ACTIVE = (1 << 4),
DDP_TASK_ACTIVE = (1 << 5),
DDP_DEAD = (1 << 6),
DDP_AIO = (1 << 7),
DDP_RCVBUF = (1 << 8),
};
struct bio;
struct ctl_sg_entry;
struct sockopt;
struct offload_settings;
struct conn_params {
int8_t rx_coalesce;
int8_t cong_algo;
int8_t tc_idx;
int8_t tstamp;
int8_t sack;
int8_t nagle;
int8_t keepalive;
int8_t wscale;
int8_t ecn;
int8_t mtu_idx;
int8_t ulp_mode;
int8_t tx_align;
int8_t ctrlq_idx;
int16_t txq_idx;
int16_t rxq_idx;
int16_t l2t_idx;
uint16_t emss;
uint16_t opt0_bufsize;
u_int sndbuf;
};
struct ofld_tx_sdesc {
uint32_t plen : 26;
uint32_t tx_credits : 6;
};
#define MAX_OFLD_TX_SDESC_PLEN ((1u << 26) - 1)
#define MAX_OFLD_TX_SDESC_CREDITS ((1u << 6) - 1)
struct ppod_region {
u_int pr_start;
u_int pr_len;
u_int pr_page_shift[4];
uint32_t pr_tag_mask;
uint32_t pr_invalid_bit;
uint32_t pr_alias_mask;
u_int pr_alias_shift;
vmem_t *pr_arena;
};
struct ppod_reservation {
struct ppod_region *prsv_pr;
uint32_t prsv_tag;
u_int prsv_nppods;
};
struct pageset {
TAILQ_ENTRY(pageset) link;
vm_page_t *pages;
int npages;
int flags;
int offset;
int len;
struct ppod_reservation prsv;
struct vmspace *vm;
vm_offset_t start;
u_int vm_timestamp;
};
TAILQ_HEAD(pagesetq, pageset);
#define PS_PPODS_WRITTEN 0x0001
struct ddp_rcv_buffer {
TAILQ_ENTRY(ddp_rcv_buffer) link;
void *buf;
struct ppod_reservation prsv;
size_t len;
u_int refs;
};
struct ddp_buffer {
union {
struct {
struct pageset *ps;
struct kaiocb *job;
int cancel_pending;
};
struct {
struct ddp_rcv_buffer *drb;
uint32_t placed;
};
};
};
struct ddp_pcb {
struct mtx lock;
u_int flags;
int active_id;
struct ddp_buffer db[2];
union {
TAILQ_HEAD(, pageset) cached_pagesets;
TAILQ_HEAD(, ddp_rcv_buffer) cached_buffers;
};
TAILQ_HEAD(, kaiocb) aiojobq;
u_int waiting_count;
u_int active_count;
u_int cached_count;
struct task requeue_task;
struct kaiocb *queueing;
struct mtx cache_lock;
};
struct toepcb {
struct tom_data *td;
struct inpcb *inp;
u_int flags;
TAILQ_ENTRY(toepcb) link;
int refcount;
struct vnet *vnet;
struct vi_info *vi;
struct sge_ofld_txq *ofld_txq;
struct sge_ofld_rxq *ofld_rxq;
struct sge_wrq *ctrlq;
struct l2t_entry *l2te;
struct clip_entry *ce;
int tid;
int incarnation;
u_int tx_total;
u_int tx_credits;
u_int tx_nocompl;
u_int plen_nocompl;
struct conn_params params;
void *ulpcb;
void *ulpcb2;
struct mbufq ulp_pduq;
struct mbufq ulp_pdu_reclaimq;
struct ddp_pcb ddp;
struct tls_ofld_info tls;
TAILQ_HEAD(, kaiocb) aiotx_jobq;
struct task aiotx_task;
struct socket *aiotx_so;
uint8_t txsd_total;
uint8_t txsd_pidx;
uint8_t txsd_cidx;
uint8_t txsd_avail;
struct ofld_tx_sdesc txsd[];
};
static inline int
ulp_mode(struct toepcb *toep)
{
return (toep->params.ulp_mode);
}
#define DDP_LOCK(toep) mtx_lock(&(toep)->ddp.lock)
#define DDP_UNLOCK(toep) mtx_unlock(&(toep)->ddp.lock)
#define DDP_ASSERT_LOCKED(toep) mtx_assert(&(toep)->ddp.lock, MA_OWNED)
#define DDP_CACHE_LOCK(toep) mtx_lock(&(toep)->ddp.cache_lock)
#define DDP_CACHE_UNLOCK(toep) mtx_unlock(&(toep)->ddp.cache_lock)
struct synq_entry {
struct listen_ctx *lctx;
struct mbuf *syn;
int flags;
TAILQ_ENTRY(synq_entry) link;
volatile int ok_to_respond;
volatile u_int refcnt;
int tid;
uint32_t iss;
uint32_t irs;
uint32_t ts;
uint32_t rss_hash;
__be16 tcp_opt;
int incarnation;
struct toepcb *toep;
struct conn_params params;
};
#define LCTX_RPL_PENDING 1
#define LCTX_SETUP_IN_HW 2
struct listen_ctx {
LIST_ENTRY(listen_ctx) link;
volatile int refcount;
int stid;
int flags;
bool isipv6;
struct inpcb *inp;
struct vnet *vnet;
struct sge_wrq *ctrlq;
struct sge_ofld_rxq *ofld_rxq;
struct clip_entry *ce;
};
#define TE_RPL_PENDING 1
#define TE_ACTIVE 2
#define TS_RTO (1 << 0)
#define TS_DUPACKS (1 << 1)
#define TS_FASTREXMT (1 << 2)
#define TS_SND_BACKLOGGED (1 << 3)
#define TS_CWND_LIMITED (1 << 4)
#define TS_ECN_ECE (1 << 5)
#define TS_ECN_CWR (1 << 6)
#define TS_RESERVED (1 << 7)
struct tcb_histent {
struct mtx te_lock;
struct callout te_callout;
uint64_t te_tcb[TCB_SIZE / sizeof(uint64_t)];
struct adapter *te_adapter;
u_int te_flags;
u_int te_tid;
uint8_t te_pidx;
uint8_t te_sample[100];
};
struct tom_data {
struct toedev tod;
struct mtx toep_list_lock;
TAILQ_HEAD(, toepcb) toep_list;
TAILQ_HEAD(, synq_entry) synqe_list;
TAILQ_HEAD(, toepcb) stranded_atids;
TAILQ_HEAD(, toepcb) stranded_tids;
TAILQ_HEAD(, synq_entry) stranded_synqe;
struct task cleanup_stranded_tids;
struct mtx lctx_hash_lock;
LIST_HEAD(, listen_ctx) *listen_hash;
u_long listen_mask;
int lctx_count;
struct ppod_region pr;
struct rwlock tcb_history_lock __aligned(CACHE_LINE_SIZE);
struct tcb_histent **tcb_history;
int dupack_threshold;
struct mtx unsent_wr_lock;
STAILQ_HEAD(, wrqe) unsent_wr_list;
struct task reclaim_wr_resources;
};
static inline struct tom_data *
tod_td(struct toedev *tod)
{
return (__containerof(tod, struct tom_data, tod));
}
static inline struct adapter *
td_adapter(struct tom_data *td)
{
return (td->tod.tod_softc);
}
static inline void
set_mbuf_raw_wr(struct mbuf *m, bool raw)
{
M_ASSERTPKTHDR(m);
m->m_pkthdr.PH_per.eight[6] = raw;
}
static inline bool
mbuf_raw_wr(struct mbuf *m)
{
M_ASSERTPKTHDR(m);
return (m->m_pkthdr.PH_per.eight[6]);
}
static inline void
set_mbuf_ulp_submode(struct mbuf *m, uint8_t ulp_submode)
{
M_ASSERTPKTHDR(m);
m->m_pkthdr.PH_per.eight[0] = ulp_submode;
}
static inline uint8_t
mbuf_ulp_submode(struct mbuf *m)
{
M_ASSERTPKTHDR(m);
return (m->m_pkthdr.PH_per.eight[0]);
}
static inline void
set_mbuf_iscsi_iso(struct mbuf *m, bool iso)
{
M_ASSERTPKTHDR(m);
m->m_pkthdr.PH_per.eight[1] = iso;
}
static inline bool
mbuf_iscsi_iso(struct mbuf *m)
{
M_ASSERTPKTHDR(m);
return (m->m_pkthdr.PH_per.eight[1]);
}
#define CXGBE_ISO_TYPE(flags) ((flags) & 0x3)
#define CXGBE_ISO_F 0x4
static inline void
set_mbuf_iscsi_iso_flags(struct mbuf *m, uint8_t flags)
{
M_ASSERTPKTHDR(m);
m->m_pkthdr.PH_per.eight[2] = flags;
}
static inline uint8_t
mbuf_iscsi_iso_flags(struct mbuf *m)
{
M_ASSERTPKTHDR(m);
return (m->m_pkthdr.PH_per.eight[2]);
}
static inline void
set_mbuf_iscsi_iso_mss(struct mbuf *m, uint16_t mss)
{
M_ASSERTPKTHDR(m);
m->m_pkthdr.PH_per.sixteen[2] = mss;
}
static inline uint16_t
mbuf_iscsi_iso_mss(struct mbuf *m)
{
M_ASSERTPKTHDR(m);
return (m->m_pkthdr.PH_per.sixteen[2]);
}
struct toepcb *alloc_toepcb(struct vi_info *, int);
int init_toepcb(struct vi_info *, struct toepcb *);
struct toepcb *hold_toepcb(struct toepcb *);
void free_toepcb(struct toepcb *);
void offload_socket(struct socket *, struct toepcb *);
void restore_so_proto(struct socket *, bool);
void undo_offload_socket(struct socket *);
void final_cpl_received(struct toepcb *);
void insert_tid(struct adapter *, int, void *, int);
void *lookup_tid(struct adapter *, int);
void update_tid(struct adapter *, int, void *);
void remove_tid(struct adapter *, int, int);
u_long select_rcv_wnd(struct socket *);
int select_rcv_wscale(void);
void init_conn_params(struct vi_info *, struct offload_settings *,
struct in_conninfo *, struct socket *, const struct tcp_options *, int16_t,
struct conn_params *cp);
void update_tid_qid_sel(struct vi_info *, struct conn_params *, int);
__be64 calc_options0(struct vi_info *, struct conn_params *);
__be32 calc_options2(struct vi_info *, struct conn_params *);
uint64_t select_ntuple(struct vi_info *, struct l2t_entry *);
int negative_advice(int);
int add_tid_to_history(struct adapter *, u_int);
struct adapter *find_offload_adapter(struct socket *);
void send_txdataplen_max_flowc_wr(struct adapter *, struct toepcb *, int);
void t4_pcb_detach(struct toedev *, struct tcpcb *);
void t4_init_connect_cpl_handlers(void);
void t4_uninit_connect_cpl_handlers(void);
int t4_connect(struct toedev *, struct socket *, struct nhop_object *,
struct sockaddr *);
void act_open_failure_cleanup(struct adapter *, struct toepcb *, u_int);
void t4_init_listen_cpl_handlers(void);
void t4_uninit_listen_cpl_handlers(void);
int t4_listen_start(struct toedev *, struct tcpcb *);
int t4_listen_stop(struct toedev *, struct tcpcb *);
void t4_syncache_added(struct toedev *, void *);
void t4_syncache_removed(struct toedev *, void *);
int t4_syncache_respond(struct toedev *, void *, struct mbuf *);
int do_abort_req_synqe(struct sge_iq *, const struct rss_header *,
struct mbuf *);
int do_abort_rpl_synqe(struct sge_iq *, const struct rss_header *,
struct mbuf *);
void t4_offload_socket(struct toedev *, void *, struct socket *);
void synack_failure_cleanup(struct adapter *, struct synq_entry *);
int alloc_stid_tab(struct adapter *);
void free_stid_tab(struct adapter *);
void stop_stid_tab(struct adapter *);
void restart_stid_tab(struct adapter *);
void aiotx_init_toep(struct toepcb *);
int t4_aio_queue_aiotx(struct socket *, struct kaiocb *);
void t4_init_cpl_io_handlers(void);
void t4_uninit_cpl_io_handlers(void);
void send_abort_rpl(struct adapter *, struct sge_ofld_txq *, int , int);
void send_flowc_wr(struct toepcb *, struct tcpcb *);
void send_reset(struct adapter *, struct toepcb *, uint32_t);
int send_rx_credits(struct adapter *, struct toepcb *, int);
void make_established(struct toepcb *, uint32_t, uint32_t, uint16_t);
int t4_close_conn(struct adapter *, struct toepcb *);
void t4_rcvd(struct toedev *, struct tcpcb *);
void t4_rcvd_locked(struct toedev *, struct tcpcb *);
int t4_tod_output(struct toedev *, struct tcpcb *);
int t4_send_fin(struct toedev *, struct tcpcb *);
int t4_send_rst(struct toedev *, struct tcpcb *);
void t4_set_tcb_field(struct adapter *, struct sge_wrq *, struct toepcb *,
uint16_t, uint64_t, uint64_t, int, int);
void t4_push_pdus(struct adapter *, struct toepcb *, int);
bool t4_push_raw_wr(struct adapter *, struct toepcb *, struct mbuf *);
void t4_raw_wr_tx(struct adapter *, struct toepcb *, struct mbuf *);
void write_set_tcb_field(struct adapter *, void *, struct toepcb *, uint16_t,
uint64_t, uint64_t, int, int);
int t4_init_ppod_region(struct ppod_region *, struct t4_range *, u_int,
const char *);
void t4_free_ppod_region(struct ppod_region *);
int t4_alloc_page_pods_for_ps(struct ppod_region *, struct pageset *);
int t4_alloc_page_pods_for_bio(struct ppod_region *, struct bio *,
struct ppod_reservation *);
int t4_alloc_page_pods_for_buf(struct ppod_region *, vm_offset_t, int,
struct ppod_reservation *);
int t4_alloc_page_pods_for_sgl(struct ppod_region *, struct ctl_sg_entry *, int,
struct ppod_reservation *);
int t4_write_page_pods_for_ps(struct adapter *, struct sge_wrq *, int,
struct pageset *);
int t4_write_page_pods_for_bio(struct adapter *, struct toepcb *,
struct ppod_reservation *, struct bio *, struct mbufq *);
int t4_write_page_pods_for_buf(struct adapter *, struct toepcb *,
struct ppod_reservation *, vm_offset_t, int, struct mbufq *);
int t4_write_page_pods_for_sgl(struct adapter *, struct toepcb *,
struct ppod_reservation *, struct ctl_sg_entry *, int, int, struct mbufq *);
void t4_free_page_pods(struct ppod_reservation *);
int t4_aio_queue_ddp(struct socket *, struct kaiocb *);
int t4_enable_ddp_rcv(struct socket *, struct toepcb *);
void t4_ddp_mod_load(void);
void t4_ddp_mod_unload(void);
struct mbuf *alloc_raw_wr_mbuf(int);
void ddp_assert_empty(struct toepcb *);
void ddp_uninit_toep(struct toepcb *);
void ddp_queue_toep(struct toepcb *);
void release_ddp_resources(struct toepcb *toep);
void handle_ddp_close(struct toepcb *, struct tcpcb *, uint32_t);
void handle_ddp_indicate(struct toepcb *);
void insert_ddp_data(struct toepcb *, uint32_t);
const struct offload_settings *lookup_offload_policy(struct adapter *, int,
struct mbuf *, uint16_t, struct inpcb *);
bool can_tls_offload(struct adapter *);
void do_rx_data_tls(const struct cpl_rx_data *, struct toepcb *, struct mbuf *);
void t4_push_ktls(struct adapter *, struct toepcb *, int);
void tls_received_starting_data(struct adapter *, struct toepcb *,
struct sockbuf *, int);
void t4_tls_mod_load(void);
void t4_tls_mod_unload(void);
void tls_init_toep(struct toepcb *);
int tls_tx_key(struct toepcb *);
void tls_uninit_toep(struct toepcb *);
int tls_alloc_ktls(struct toepcb *, struct ktls_session *, int);
uint32_t t4_pblpool_alloc(struct adapter *, int);
void t4_pblpool_free(struct adapter *, uint32_t, int);
int t4_pblpool_create(struct adapter *);
void t4_pblpool_destroy(struct adapter *);
#endif