162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _RDS_IB_H
362306a36Sopenharmony_ci#define _RDS_IB_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <rdma/ib_verbs.h>
662306a36Sopenharmony_ci#include <rdma/rdma_cm.h>
762306a36Sopenharmony_ci#include <linux/interrupt.h>
862306a36Sopenharmony_ci#include <linux/pci.h>
962306a36Sopenharmony_ci#include <linux/slab.h>
1062306a36Sopenharmony_ci#include "rds.h"
1162306a36Sopenharmony_ci#include "rdma_transport.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#define RDS_IB_MAX_SGE			8
1462306a36Sopenharmony_ci#define RDS_IB_RECV_SGE 		2
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define RDS_IB_DEFAULT_RECV_WR		1024
1762306a36Sopenharmony_ci#define RDS_IB_DEFAULT_SEND_WR		256
1862306a36Sopenharmony_ci#define RDS_IB_DEFAULT_FR_WR		512
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define RDS_IB_DEFAULT_RETRY_COUNT	1
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define RDS_IB_SUPPORTED_PROTOCOLS	0x00000003	/* minor versions supported */
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define RDS_IB_RECYCLE_BATCH_COUNT	32
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define RDS_IB_WC_MAX			32
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ciextern struct rw_semaphore rds_ib_devices_lock;
2962306a36Sopenharmony_ciextern struct list_head rds_ib_devices;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci/*
3262306a36Sopenharmony_ci * IB posts RDS_FRAG_SIZE fragments of pages to the receive queues to
3362306a36Sopenharmony_ci * try and minimize the amount of memory tied up both the device and
3462306a36Sopenharmony_ci * socket receive queues.
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_cistruct rds_page_frag {
3762306a36Sopenharmony_ci	struct list_head	f_item;
3862306a36Sopenharmony_ci	struct list_head	f_cache_entry;
3962306a36Sopenharmony_ci	struct scatterlist	f_sg;
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistruct rds_ib_incoming {
4362306a36Sopenharmony_ci	struct list_head	ii_frags;
4462306a36Sopenharmony_ci	struct list_head	ii_cache_entry;
4562306a36Sopenharmony_ci	struct rds_incoming	ii_inc;
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistruct rds_ib_cache_head {
4962306a36Sopenharmony_ci	struct list_head *first;
5062306a36Sopenharmony_ci	unsigned long count;
5162306a36Sopenharmony_ci};
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistruct rds_ib_refill_cache {
5462306a36Sopenharmony_ci	struct rds_ib_cache_head __percpu *percpu;
5562306a36Sopenharmony_ci	struct list_head	 *xfer;
5662306a36Sopenharmony_ci	struct list_head	 *ready;
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/* This is the common structure for the IB private data exchange in setting up
6062306a36Sopenharmony_ci * an RDS connection.  The exchange is different for IPv4 and IPv6 connections.
6162306a36Sopenharmony_ci * The reason is that the address size is different and the addresses
6262306a36Sopenharmony_ci * exchanged are in the beginning of the structure.  Hence it is not possible
6362306a36Sopenharmony_ci * for interoperability if same structure is used.
6462306a36Sopenharmony_ci */
6562306a36Sopenharmony_cistruct rds_ib_conn_priv_cmn {
6662306a36Sopenharmony_ci	u8			ricpc_protocol_major;
6762306a36Sopenharmony_ci	u8			ricpc_protocol_minor;
6862306a36Sopenharmony_ci	__be16			ricpc_protocol_minor_mask;	/* bitmask */
6962306a36Sopenharmony_ci	u8			ricpc_dp_toss;
7062306a36Sopenharmony_ci	u8			ripc_reserved1;
7162306a36Sopenharmony_ci	__be16			ripc_reserved2;
7262306a36Sopenharmony_ci	__be64			ricpc_ack_seq;
7362306a36Sopenharmony_ci	__be32			ricpc_credit;	/* non-zero enables flow ctl */
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistruct rds_ib_connect_private {
7762306a36Sopenharmony_ci	/* Add new fields at the end, and don't permute existing fields. */
7862306a36Sopenharmony_ci	__be32				dp_saddr;
7962306a36Sopenharmony_ci	__be32				dp_daddr;
8062306a36Sopenharmony_ci	struct rds_ib_conn_priv_cmn	dp_cmn;
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistruct rds6_ib_connect_private {
8462306a36Sopenharmony_ci	/* Add new fields at the end, and don't permute existing fields. */
8562306a36Sopenharmony_ci	struct in6_addr			dp_saddr;
8662306a36Sopenharmony_ci	struct in6_addr			dp_daddr;
8762306a36Sopenharmony_ci	struct rds_ib_conn_priv_cmn	dp_cmn;
8862306a36Sopenharmony_ci};
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define dp_protocol_major	dp_cmn.ricpc_protocol_major
9162306a36Sopenharmony_ci#define dp_protocol_minor	dp_cmn.ricpc_protocol_minor
9262306a36Sopenharmony_ci#define dp_protocol_minor_mask	dp_cmn.ricpc_protocol_minor_mask
9362306a36Sopenharmony_ci#define dp_ack_seq		dp_cmn.ricpc_ack_seq
9462306a36Sopenharmony_ci#define dp_credit		dp_cmn.ricpc_credit
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ciunion rds_ib_conn_priv {
9762306a36Sopenharmony_ci	struct rds_ib_connect_private	ricp_v4;
9862306a36Sopenharmony_ci	struct rds6_ib_connect_private	ricp_v6;
9962306a36Sopenharmony_ci};
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistruct rds_ib_send_work {
10262306a36Sopenharmony_ci	void			*s_op;
10362306a36Sopenharmony_ci	union {
10462306a36Sopenharmony_ci		struct ib_send_wr	s_wr;
10562306a36Sopenharmony_ci		struct ib_rdma_wr	s_rdma_wr;
10662306a36Sopenharmony_ci		struct ib_atomic_wr	s_atomic_wr;
10762306a36Sopenharmony_ci	};
10862306a36Sopenharmony_ci	struct ib_sge		s_sge[RDS_IB_MAX_SGE];
10962306a36Sopenharmony_ci	unsigned long		s_queued;
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistruct rds_ib_recv_work {
11362306a36Sopenharmony_ci	struct rds_ib_incoming 	*r_ibinc;
11462306a36Sopenharmony_ci	struct rds_page_frag	*r_frag;
11562306a36Sopenharmony_ci	struct ib_recv_wr	r_wr;
11662306a36Sopenharmony_ci	struct ib_sge		r_sge[2];
11762306a36Sopenharmony_ci};
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistruct rds_ib_work_ring {
12062306a36Sopenharmony_ci	u32		w_nr;
12162306a36Sopenharmony_ci	u32		w_alloc_ptr;
12262306a36Sopenharmony_ci	u32		w_alloc_ctr;
12362306a36Sopenharmony_ci	u32		w_free_ptr;
12462306a36Sopenharmony_ci	atomic_t	w_free_ctr;
12562306a36Sopenharmony_ci};
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/* Rings are posted with all the allocations they'll need to queue the
12862306a36Sopenharmony_ci * incoming message to the receiving socket so this can't fail.
12962306a36Sopenharmony_ci * All fragments start with a header, so we can make sure we're not receiving
13062306a36Sopenharmony_ci * garbage, and we can tell a small 8 byte fragment from an ACK frame.
13162306a36Sopenharmony_ci */
13262306a36Sopenharmony_cistruct rds_ib_ack_state {
13362306a36Sopenharmony_ci	u64		ack_next;
13462306a36Sopenharmony_ci	u64		ack_recv;
13562306a36Sopenharmony_ci	unsigned int	ack_required:1;
13662306a36Sopenharmony_ci	unsigned int	ack_next_valid:1;
13762306a36Sopenharmony_ci	unsigned int	ack_recv_valid:1;
13862306a36Sopenharmony_ci};
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistruct rds_ib_device;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistruct rds_ib_connection {
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	struct list_head	ib_node;
14662306a36Sopenharmony_ci	struct rds_ib_device	*rds_ibdev;
14762306a36Sopenharmony_ci	struct rds_connection	*conn;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	/* alphabet soup, IBTA style */
15062306a36Sopenharmony_ci	struct rdma_cm_id	*i_cm_id;
15162306a36Sopenharmony_ci	struct ib_pd		*i_pd;
15262306a36Sopenharmony_ci	struct ib_cq		*i_send_cq;
15362306a36Sopenharmony_ci	struct ib_cq		*i_recv_cq;
15462306a36Sopenharmony_ci	struct ib_wc		i_send_wc[RDS_IB_WC_MAX];
15562306a36Sopenharmony_ci	struct ib_wc		i_recv_wc[RDS_IB_WC_MAX];
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	/* To control the number of wrs from fastreg */
15862306a36Sopenharmony_ci	atomic_t		i_fastreg_wrs;
15962306a36Sopenharmony_ci	atomic_t		i_fastreg_inuse_count;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	/* interrupt handling */
16262306a36Sopenharmony_ci	struct tasklet_struct	i_send_tasklet;
16362306a36Sopenharmony_ci	struct tasklet_struct	i_recv_tasklet;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	/* tx */
16662306a36Sopenharmony_ci	struct rds_ib_work_ring	i_send_ring;
16762306a36Sopenharmony_ci	struct rm_data_op	*i_data_op;
16862306a36Sopenharmony_ci	struct rds_header	**i_send_hdrs;
16962306a36Sopenharmony_ci	dma_addr_t		*i_send_hdrs_dma;
17062306a36Sopenharmony_ci	struct rds_ib_send_work *i_sends;
17162306a36Sopenharmony_ci	atomic_t		i_signaled_sends;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	/* rx */
17462306a36Sopenharmony_ci	struct mutex		i_recv_mutex;
17562306a36Sopenharmony_ci	struct rds_ib_work_ring	i_recv_ring;
17662306a36Sopenharmony_ci	struct rds_ib_incoming	*i_ibinc;
17762306a36Sopenharmony_ci	u32			i_recv_data_rem;
17862306a36Sopenharmony_ci	struct rds_header	**i_recv_hdrs;
17962306a36Sopenharmony_ci	dma_addr_t		*i_recv_hdrs_dma;
18062306a36Sopenharmony_ci	struct rds_ib_recv_work *i_recvs;
18162306a36Sopenharmony_ci	u64			i_ack_recv;	/* last ACK received */
18262306a36Sopenharmony_ci	struct rds_ib_refill_cache i_cache_incs;
18362306a36Sopenharmony_ci	struct rds_ib_refill_cache i_cache_frags;
18462306a36Sopenharmony_ci	atomic_t		i_cache_allocs;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	/* sending acks */
18762306a36Sopenharmony_ci	unsigned long		i_ack_flags;
18862306a36Sopenharmony_ci#ifdef KERNEL_HAS_ATOMIC64
18962306a36Sopenharmony_ci	atomic64_t		i_ack_next;	/* next ACK to send */
19062306a36Sopenharmony_ci#else
19162306a36Sopenharmony_ci	spinlock_t		i_ack_lock;	/* protect i_ack_next */
19262306a36Sopenharmony_ci	u64			i_ack_next;	/* next ACK to send */
19362306a36Sopenharmony_ci#endif
19462306a36Sopenharmony_ci	struct rds_header	*i_ack;
19562306a36Sopenharmony_ci	struct ib_send_wr	i_ack_wr;
19662306a36Sopenharmony_ci	struct ib_sge		i_ack_sge;
19762306a36Sopenharmony_ci	dma_addr_t		i_ack_dma;
19862306a36Sopenharmony_ci	unsigned long		i_ack_queued;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	/* Flow control related information
20162306a36Sopenharmony_ci	 *
20262306a36Sopenharmony_ci	 * Our algorithm uses a pair variables that we need to access
20362306a36Sopenharmony_ci	 * atomically - one for the send credits, and one posted
20462306a36Sopenharmony_ci	 * recv credits we need to transfer to remote.
20562306a36Sopenharmony_ci	 * Rather than protect them using a slow spinlock, we put both into
20662306a36Sopenharmony_ci	 * a single atomic_t and update it using cmpxchg
20762306a36Sopenharmony_ci	 */
20862306a36Sopenharmony_ci	atomic_t		i_credits;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	/* Protocol version specific information */
21162306a36Sopenharmony_ci	unsigned int		i_flowctl:1;	/* enable/disable flow ctl */
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	/* Batched completions */
21462306a36Sopenharmony_ci	unsigned int		i_unsignaled_wrs;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	/* Endpoint role in connection */
21762306a36Sopenharmony_ci	bool			i_active_side;
21862306a36Sopenharmony_ci	atomic_t		i_cq_quiesce;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	/* Send/Recv vectors */
22162306a36Sopenharmony_ci	int			i_scq_vector;
22262306a36Sopenharmony_ci	int			i_rcq_vector;
22362306a36Sopenharmony_ci	u8			i_sl;
22462306a36Sopenharmony_ci};
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci/* This assumes that atomic_t is at least 32 bits */
22762306a36Sopenharmony_ci#define IB_GET_SEND_CREDITS(v)	((v) & 0xffff)
22862306a36Sopenharmony_ci#define IB_GET_POST_CREDITS(v)	((v) >> 16)
22962306a36Sopenharmony_ci#define IB_SET_SEND_CREDITS(v)	((v) & 0xffff)
23062306a36Sopenharmony_ci#define IB_SET_POST_CREDITS(v)	((v) << 16)
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistruct rds_ib_ipaddr {
23362306a36Sopenharmony_ci	struct list_head	list;
23462306a36Sopenharmony_ci	__be32			ipaddr;
23562306a36Sopenharmony_ci	struct rcu_head		rcu;
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cienum {
23962306a36Sopenharmony_ci	RDS_IB_MR_8K_POOL,
24062306a36Sopenharmony_ci	RDS_IB_MR_1M_POOL,
24162306a36Sopenharmony_ci};
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistruct rds_ib_device {
24462306a36Sopenharmony_ci	struct list_head	list;
24562306a36Sopenharmony_ci	struct list_head	ipaddr_list;
24662306a36Sopenharmony_ci	struct list_head	conn_list;
24762306a36Sopenharmony_ci	struct ib_device	*dev;
24862306a36Sopenharmony_ci	struct ib_pd		*pd;
24962306a36Sopenharmony_ci	u8			odp_capable:1;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	unsigned int		max_mrs;
25262306a36Sopenharmony_ci	struct rds_ib_mr_pool	*mr_1m_pool;
25362306a36Sopenharmony_ci	struct rds_ib_mr_pool   *mr_8k_pool;
25462306a36Sopenharmony_ci	unsigned int		max_8k_mrs;
25562306a36Sopenharmony_ci	unsigned int		max_1m_mrs;
25662306a36Sopenharmony_ci	int			max_sge;
25762306a36Sopenharmony_ci	unsigned int		max_wrs;
25862306a36Sopenharmony_ci	unsigned int		max_initiator_depth;
25962306a36Sopenharmony_ci	unsigned int		max_responder_resources;
26062306a36Sopenharmony_ci	spinlock_t		spinlock;	/* protect the above */
26162306a36Sopenharmony_ci	refcount_t		refcount;
26262306a36Sopenharmony_ci	struct work_struct	free_work;
26362306a36Sopenharmony_ci	int			*vector_load;
26462306a36Sopenharmony_ci};
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci#define rdsibdev_to_node(rdsibdev) ibdev_to_node(rdsibdev->dev)
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci/* bits for i_ack_flags */
26962306a36Sopenharmony_ci#define IB_ACK_IN_FLIGHT	0
27062306a36Sopenharmony_ci#define IB_ACK_REQUESTED	1
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci/* Magic WR_ID for ACKs */
27362306a36Sopenharmony_ci#define RDS_IB_ACK_WR_ID	(~(u64) 0)
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistruct rds_ib_statistics {
27662306a36Sopenharmony_ci	uint64_t	s_ib_connect_raced;
27762306a36Sopenharmony_ci	uint64_t	s_ib_listen_closed_stale;
27862306a36Sopenharmony_ci	uint64_t	s_ib_evt_handler_call;
27962306a36Sopenharmony_ci	uint64_t	s_ib_tasklet_call;
28062306a36Sopenharmony_ci	uint64_t	s_ib_tx_cq_event;
28162306a36Sopenharmony_ci	uint64_t	s_ib_tx_ring_full;
28262306a36Sopenharmony_ci	uint64_t	s_ib_tx_throttle;
28362306a36Sopenharmony_ci	uint64_t	s_ib_tx_sg_mapping_failure;
28462306a36Sopenharmony_ci	uint64_t	s_ib_tx_stalled;
28562306a36Sopenharmony_ci	uint64_t	s_ib_tx_credit_updates;
28662306a36Sopenharmony_ci	uint64_t	s_ib_rx_cq_event;
28762306a36Sopenharmony_ci	uint64_t	s_ib_rx_ring_empty;
28862306a36Sopenharmony_ci	uint64_t	s_ib_rx_refill_from_cq;
28962306a36Sopenharmony_ci	uint64_t	s_ib_rx_refill_from_thread;
29062306a36Sopenharmony_ci	uint64_t	s_ib_rx_alloc_limit;
29162306a36Sopenharmony_ci	uint64_t	s_ib_rx_total_frags;
29262306a36Sopenharmony_ci	uint64_t	s_ib_rx_total_incs;
29362306a36Sopenharmony_ci	uint64_t	s_ib_rx_credit_updates;
29462306a36Sopenharmony_ci	uint64_t	s_ib_ack_sent;
29562306a36Sopenharmony_ci	uint64_t	s_ib_ack_send_failure;
29662306a36Sopenharmony_ci	uint64_t	s_ib_ack_send_delayed;
29762306a36Sopenharmony_ci	uint64_t	s_ib_ack_send_piggybacked;
29862306a36Sopenharmony_ci	uint64_t	s_ib_ack_received;
29962306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_8k_alloc;
30062306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_8k_free;
30162306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_8k_used;
30262306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_8k_pool_flush;
30362306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_8k_pool_wait;
30462306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_8k_pool_depleted;
30562306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_1m_alloc;
30662306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_1m_free;
30762306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_1m_used;
30862306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_1m_pool_flush;
30962306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_1m_pool_wait;
31062306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_1m_pool_depleted;
31162306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_8k_reused;
31262306a36Sopenharmony_ci	uint64_t	s_ib_rdma_mr_1m_reused;
31362306a36Sopenharmony_ci	uint64_t	s_ib_atomic_cswp;
31462306a36Sopenharmony_ci	uint64_t	s_ib_atomic_fadd;
31562306a36Sopenharmony_ci	uint64_t	s_ib_recv_added_to_cache;
31662306a36Sopenharmony_ci	uint64_t	s_ib_recv_removed_from_cache;
31762306a36Sopenharmony_ci};
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ciextern struct workqueue_struct *rds_ib_wq;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci/*
32262306a36Sopenharmony_ci * Fake ib_dma_sync_sg_for_{cpu,device} as long as ib_verbs.h
32362306a36Sopenharmony_ci * doesn't define it.
32462306a36Sopenharmony_ci */
32562306a36Sopenharmony_cistatic inline void rds_ib_dma_sync_sg_for_cpu(struct ib_device *dev,
32662306a36Sopenharmony_ci					      struct scatterlist *sglist,
32762306a36Sopenharmony_ci					      unsigned int sg_dma_len,
32862306a36Sopenharmony_ci					      int direction)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	struct scatterlist *sg;
33162306a36Sopenharmony_ci	unsigned int i;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	for_each_sg(sglist, sg, sg_dma_len, i) {
33462306a36Sopenharmony_ci		ib_dma_sync_single_for_cpu(dev, sg_dma_address(sg),
33562306a36Sopenharmony_ci					   sg_dma_len(sg), direction);
33662306a36Sopenharmony_ci	}
33762306a36Sopenharmony_ci}
33862306a36Sopenharmony_ci#define ib_dma_sync_sg_for_cpu	rds_ib_dma_sync_sg_for_cpu
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_cistatic inline void rds_ib_dma_sync_sg_for_device(struct ib_device *dev,
34162306a36Sopenharmony_ci						 struct scatterlist *sglist,
34262306a36Sopenharmony_ci						 unsigned int sg_dma_len,
34362306a36Sopenharmony_ci						 int direction)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct scatterlist *sg;
34662306a36Sopenharmony_ci	unsigned int i;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	for_each_sg(sglist, sg, sg_dma_len, i) {
34962306a36Sopenharmony_ci		ib_dma_sync_single_for_device(dev, sg_dma_address(sg),
35062306a36Sopenharmony_ci					      sg_dma_len(sg), direction);
35162306a36Sopenharmony_ci	}
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci#define ib_dma_sync_sg_for_device	rds_ib_dma_sync_sg_for_device
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci/* ib.c */
35762306a36Sopenharmony_ciextern struct rds_transport rds_ib_transport;
35862306a36Sopenharmony_cistruct rds_ib_device *rds_ib_get_client_data(struct ib_device *device);
35962306a36Sopenharmony_civoid rds_ib_dev_put(struct rds_ib_device *rds_ibdev);
36062306a36Sopenharmony_ciextern struct ib_client rds_ib_client;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ciextern unsigned int rds_ib_retry_count;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ciextern spinlock_t ib_nodev_conns_lock;
36562306a36Sopenharmony_ciextern struct list_head ib_nodev_conns;
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci/* ib_cm.c */
36862306a36Sopenharmony_ciint rds_ib_conn_alloc(struct rds_connection *conn, gfp_t gfp);
36962306a36Sopenharmony_civoid rds_ib_conn_free(void *arg);
37062306a36Sopenharmony_ciint rds_ib_conn_path_connect(struct rds_conn_path *cp);
37162306a36Sopenharmony_civoid rds_ib_conn_path_shutdown(struct rds_conn_path *cp);
37262306a36Sopenharmony_civoid rds_ib_state_change(struct sock *sk);
37362306a36Sopenharmony_ciint rds_ib_listen_init(void);
37462306a36Sopenharmony_civoid rds_ib_listen_stop(void);
37562306a36Sopenharmony_ci__printf(2, 3)
37662306a36Sopenharmony_civoid __rds_ib_conn_error(struct rds_connection *conn, const char *, ...);
37762306a36Sopenharmony_ciint rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
37862306a36Sopenharmony_ci			     struct rdma_cm_event *event, bool isv6);
37962306a36Sopenharmony_ciint rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id, bool isv6);
38062306a36Sopenharmony_civoid rds_ib_cm_connect_complete(struct rds_connection *conn,
38162306a36Sopenharmony_ci				struct rdma_cm_event *event);
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci#define rds_ib_conn_error(conn, fmt...) \
38462306a36Sopenharmony_ci	__rds_ib_conn_error(conn, KERN_WARNING "RDS/IB: " fmt)
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci/* ib_rdma.c */
38762306a36Sopenharmony_ciint rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev,
38862306a36Sopenharmony_ci			 struct in6_addr *ipaddr);
38962306a36Sopenharmony_civoid rds_ib_add_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn);
39062306a36Sopenharmony_civoid rds_ib_remove_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn);
39162306a36Sopenharmony_civoid rds_ib_destroy_nodev_conns(void);
39262306a36Sopenharmony_civoid rds_ib_mr_cqe_handler(struct rds_ib_connection *ic, struct ib_wc *wc);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci/* ib_recv.c */
39562306a36Sopenharmony_ciint rds_ib_recv_init(void);
39662306a36Sopenharmony_civoid rds_ib_recv_exit(void);
39762306a36Sopenharmony_ciint rds_ib_recv_path(struct rds_conn_path *conn);
39862306a36Sopenharmony_ciint rds_ib_recv_alloc_caches(struct rds_ib_connection *ic, gfp_t gfp);
39962306a36Sopenharmony_civoid rds_ib_recv_free_caches(struct rds_ib_connection *ic);
40062306a36Sopenharmony_civoid rds_ib_recv_refill(struct rds_connection *conn, int prefill, gfp_t gfp);
40162306a36Sopenharmony_civoid rds_ib_inc_free(struct rds_incoming *inc);
40262306a36Sopenharmony_ciint rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to);
40362306a36Sopenharmony_civoid rds_ib_recv_cqe_handler(struct rds_ib_connection *ic, struct ib_wc *wc,
40462306a36Sopenharmony_ci			     struct rds_ib_ack_state *state);
40562306a36Sopenharmony_civoid rds_ib_recv_tasklet_fn(unsigned long data);
40662306a36Sopenharmony_civoid rds_ib_recv_init_ring(struct rds_ib_connection *ic);
40762306a36Sopenharmony_civoid rds_ib_recv_clear_ring(struct rds_ib_connection *ic);
40862306a36Sopenharmony_civoid rds_ib_recv_init_ack(struct rds_ib_connection *ic);
40962306a36Sopenharmony_civoid rds_ib_attempt_ack(struct rds_ib_connection *ic);
41062306a36Sopenharmony_civoid rds_ib_ack_send_complete(struct rds_ib_connection *ic);
41162306a36Sopenharmony_ciu64 rds_ib_piggyb_ack(struct rds_ib_connection *ic);
41262306a36Sopenharmony_civoid rds_ib_set_ack(struct rds_ib_connection *ic, u64 seq, int ack_required);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci/* ib_ring.c */
41562306a36Sopenharmony_civoid rds_ib_ring_init(struct rds_ib_work_ring *ring, u32 nr);
41662306a36Sopenharmony_civoid rds_ib_ring_resize(struct rds_ib_work_ring *ring, u32 nr);
41762306a36Sopenharmony_ciu32 rds_ib_ring_alloc(struct rds_ib_work_ring *ring, u32 val, u32 *pos);
41862306a36Sopenharmony_civoid rds_ib_ring_free(struct rds_ib_work_ring *ring, u32 val);
41962306a36Sopenharmony_civoid rds_ib_ring_unalloc(struct rds_ib_work_ring *ring, u32 val);
42062306a36Sopenharmony_ciint rds_ib_ring_empty(struct rds_ib_work_ring *ring);
42162306a36Sopenharmony_ciint rds_ib_ring_low(struct rds_ib_work_ring *ring);
42262306a36Sopenharmony_ciu32 rds_ib_ring_oldest(struct rds_ib_work_ring *ring);
42362306a36Sopenharmony_ciu32 rds_ib_ring_completed(struct rds_ib_work_ring *ring, u32 wr_id, u32 oldest);
42462306a36Sopenharmony_ciextern wait_queue_head_t rds_ib_ring_empty_wait;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci/* ib_send.c */
42762306a36Sopenharmony_civoid rds_ib_xmit_path_complete(struct rds_conn_path *cp);
42862306a36Sopenharmony_ciint rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
42962306a36Sopenharmony_ci		unsigned int hdr_off, unsigned int sg, unsigned int off);
43062306a36Sopenharmony_civoid rds_ib_send_cqe_handler(struct rds_ib_connection *ic, struct ib_wc *wc);
43162306a36Sopenharmony_civoid rds_ib_send_init_ring(struct rds_ib_connection *ic);
43262306a36Sopenharmony_civoid rds_ib_send_clear_ring(struct rds_ib_connection *ic);
43362306a36Sopenharmony_ciint rds_ib_xmit_rdma(struct rds_connection *conn, struct rm_rdma_op *op);
43462306a36Sopenharmony_civoid rds_ib_send_add_credits(struct rds_connection *conn, unsigned int credits);
43562306a36Sopenharmony_civoid rds_ib_advertise_credits(struct rds_connection *conn, unsigned int posted);
43662306a36Sopenharmony_ciint rds_ib_send_grab_credits(struct rds_ib_connection *ic, u32 wanted,
43762306a36Sopenharmony_ci			     u32 *adv_credits, int need_posted, int max_posted);
43862306a36Sopenharmony_ciint rds_ib_xmit_atomic(struct rds_connection *conn, struct rm_atomic_op *op);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci/* ib_stats.c */
44162306a36Sopenharmony_ciDECLARE_PER_CPU_SHARED_ALIGNED(struct rds_ib_statistics, rds_ib_stats);
44262306a36Sopenharmony_ci#define rds_ib_stats_inc(member) rds_stats_inc_which(rds_ib_stats, member)
44362306a36Sopenharmony_ci#define rds_ib_stats_add(member, count) \
44462306a36Sopenharmony_ci		rds_stats_add_which(rds_ib_stats, member, count)
44562306a36Sopenharmony_ciunsigned int rds_ib_stats_info_copy(struct rds_info_iterator *iter,
44662306a36Sopenharmony_ci				    unsigned int avail);
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci/* ib_sysctl.c */
44962306a36Sopenharmony_ciint rds_ib_sysctl_init(void);
45062306a36Sopenharmony_civoid rds_ib_sysctl_exit(void);
45162306a36Sopenharmony_ciextern unsigned long rds_ib_sysctl_max_send_wr;
45262306a36Sopenharmony_ciextern unsigned long rds_ib_sysctl_max_recv_wr;
45362306a36Sopenharmony_ciextern unsigned long rds_ib_sysctl_max_unsig_wrs;
45462306a36Sopenharmony_ciextern unsigned long rds_ib_sysctl_max_unsig_bytes;
45562306a36Sopenharmony_ciextern unsigned long rds_ib_sysctl_max_recv_allocation;
45662306a36Sopenharmony_ciextern unsigned int rds_ib_sysctl_flow_control;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci#endif
459