xref: /openbmc/linux/net/smc/smc_wr.h (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2f38ba179SUrsula Braun /*
3f38ba179SUrsula Braun  * Shared Memory Communications over RDMA (SMC-R) and RoCE
4f38ba179SUrsula Braun  *
5f38ba179SUrsula Braun  * Work Requests exploiting Infiniband API
6f38ba179SUrsula Braun  *
7f38ba179SUrsula Braun  * Copyright IBM Corp. 2016
8f38ba179SUrsula Braun  *
9f38ba179SUrsula Braun  * Author(s):  Steffen Maier <maier@linux.vnet.ibm.com>
10f38ba179SUrsula Braun  */
11f38ba179SUrsula Braun 
12f38ba179SUrsula Braun #ifndef SMC_WR_H
13f38ba179SUrsula Braun #define SMC_WR_H
14f38ba179SUrsula Braun 
15f38ba179SUrsula Braun #include <linux/atomic.h>
16f38ba179SUrsula Braun #include <rdma/ib_verbs.h>
17f38ba179SUrsula Braun #include <asm/div64.h>
18f38ba179SUrsula Braun 
19f38ba179SUrsula Braun #include "smc.h"
20f38ba179SUrsula Braun #include "smc_core.h"
21f38ba179SUrsula Braun 
22f38ba179SUrsula Braun #define SMC_WR_BUF_CNT 16	/* # of ctrl buffers per link */
23f38ba179SUrsula Braun 
24f38ba179SUrsula Braun #define SMC_WR_TX_WAIT_FREE_SLOT_TIME	(10 * HZ)
25f38ba179SUrsula Braun 
26f38ba179SUrsula Braun #define SMC_WR_TX_SIZE 44 /* actual size of wr_send data (<=SMC_WR_BUF_SIZE) */
27f38ba179SUrsula Braun 
28f38ba179SUrsula Braun #define SMC_WR_TX_PEND_PRIV_SIZE 32
29f38ba179SUrsula Braun 
30f38ba179SUrsula Braun struct smc_wr_tx_pend_priv {
31f38ba179SUrsula Braun 	u8			priv[SMC_WR_TX_PEND_PRIV_SIZE];
32f38ba179SUrsula Braun };
33f38ba179SUrsula Braun 
34f38ba179SUrsula Braun typedef void (*smc_wr_tx_handler)(struct smc_wr_tx_pend_priv *,
35f38ba179SUrsula Braun 				  struct smc_link *,
36f38ba179SUrsula Braun 				  enum ib_wc_status);
37f38ba179SUrsula Braun 
385f08318fSUrsula Braun typedef bool (*smc_wr_tx_filter)(struct smc_wr_tx_pend_priv *,
395f08318fSUrsula Braun 				 unsigned long);
405f08318fSUrsula Braun 
415f08318fSUrsula Braun typedef void (*smc_wr_tx_dismisser)(struct smc_wr_tx_pend_priv *);
425f08318fSUrsula Braun 
43f38ba179SUrsula Braun struct smc_wr_rx_handler {
44f38ba179SUrsula Braun 	struct hlist_node	list;	/* hash table collision resolution */
45f38ba179SUrsula Braun 	void			(*handler)(struct ib_wc *, void *);
46f38ba179SUrsula Braun 	u8			type;
47f38ba179SUrsula Braun };
48f38ba179SUrsula Braun 
49f38ba179SUrsula Braun /* Only used by RDMA write WRs.
50f38ba179SUrsula Braun  * All other WRs (CDC/LLC) use smc_wr_tx_send handling WR_ID implicitly
51f38ba179SUrsula Braun  */
smc_wr_tx_get_next_wr_id(struct smc_link * link)52f38ba179SUrsula Braun static inline long smc_wr_tx_get_next_wr_id(struct smc_link *link)
53f38ba179SUrsula Braun {
54f38ba179SUrsula Braun 	return atomic_long_inc_return(&link->wr_tx_id);
55f38ba179SUrsula Braun }
56f38ba179SUrsula Braun 
smc_wr_tx_set_wr_id(atomic_long_t * wr_tx_id,long val)57f38ba179SUrsula Braun static inline void smc_wr_tx_set_wr_id(atomic_long_t *wr_tx_id, long val)
58f38ba179SUrsula Braun {
59f38ba179SUrsula Braun 	atomic_long_set(wr_tx_id, val);
60f38ba179SUrsula Braun }
61f38ba179SUrsula Braun 
smc_wr_tx_link_hold(struct smc_link * link)6295f7f3e7SKarsten Graul static inline bool smc_wr_tx_link_hold(struct smc_link *link)
6395f7f3e7SKarsten Graul {
6490cee52fSDust Li 	if (!smc_link_sendable(link))
6595f7f3e7SKarsten Graul 		return false;
66*79a22238SKai Shen 	percpu_ref_get(&link->wr_tx_refs);
6795f7f3e7SKarsten Graul 	return true;
6895f7f3e7SKarsten Graul }
6995f7f3e7SKarsten Graul 
smc_wr_tx_link_put(struct smc_link * link)7095f7f3e7SKarsten Graul static inline void smc_wr_tx_link_put(struct smc_link *link)
7195f7f3e7SKarsten Graul {
72*79a22238SKai Shen 	percpu_ref_put(&link->wr_tx_refs);
7395f7f3e7SKarsten Graul }
7495f7f3e7SKarsten Graul 
smc_wr_drain_cq(struct smc_link * lnk)75e9b1a4f8SYacan Liu static inline void smc_wr_drain_cq(struct smc_link *lnk)
76e9b1a4f8SYacan Liu {
77e9b1a4f8SYacan Liu 	wait_event(lnk->wr_rx_empty_wait, lnk->wr_rx_id_compl == lnk->wr_rx_id);
78e9b1a4f8SYacan Liu }
79e9b1a4f8SYacan Liu 
smc_wr_wakeup_tx_wait(struct smc_link * lnk)8015e1b99aSUrsula Braun static inline void smc_wr_wakeup_tx_wait(struct smc_link *lnk)
8115e1b99aSUrsula Braun {
8215e1b99aSUrsula Braun 	wake_up_all(&lnk->wr_tx_wait);
8315e1b99aSUrsula Braun }
8415e1b99aSUrsula Braun 
smc_wr_wakeup_reg_wait(struct smc_link * lnk)8515e1b99aSUrsula Braun static inline void smc_wr_wakeup_reg_wait(struct smc_link *lnk)
8615e1b99aSUrsula Braun {
8715e1b99aSUrsula Braun 	wake_up(&lnk->wr_reg_wait);
8815e1b99aSUrsula Braun }
8915e1b99aSUrsula Braun 
90f38ba179SUrsula Braun /* post a new receive work request to fill a completed old work request entry */
smc_wr_rx_post(struct smc_link * link)91f38ba179SUrsula Braun static inline int smc_wr_rx_post(struct smc_link *link)
92f38ba179SUrsula Braun {
93f38ba179SUrsula Braun 	int rc;
94f38ba179SUrsula Braun 	u64 wr_id, temp_wr_id;
95f38ba179SUrsula Braun 	u32 index;
96f38ba179SUrsula Braun 
97f38ba179SUrsula Braun 	wr_id = ++link->wr_rx_id; /* tasklet context, thus not atomic */
98f38ba179SUrsula Braun 	temp_wr_id = wr_id;
99f38ba179SUrsula Braun 	index = do_div(temp_wr_id, link->wr_rx_cnt);
100f38ba179SUrsula Braun 	link->wr_rx_ibs[index].wr_id = wr_id;
1012e3bbe46SBart Van Assche 	rc = ib_post_recv(link->roce_qp, &link->wr_rx_ibs[index], NULL);
102f38ba179SUrsula Braun 	return rc;
103f38ba179SUrsula Braun }
104f38ba179SUrsula Braun 
105f38ba179SUrsula Braun int smc_wr_create_link(struct smc_link *lnk);
106f38ba179SUrsula Braun int smc_wr_alloc_link_mem(struct smc_link *lnk);
1078799e310SKarsten Graul int smc_wr_alloc_lgr_mem(struct smc_link_group *lgr);
108f38ba179SUrsula Braun void smc_wr_free_link(struct smc_link *lnk);
109f38ba179SUrsula Braun void smc_wr_free_link_mem(struct smc_link *lnk);
1108799e310SKarsten Graul void smc_wr_free_lgr_mem(struct smc_link_group *lgr);
111f38ba179SUrsula Braun void smc_wr_remember_qp_attr(struct smc_link *lnk);
112f38ba179SUrsula Braun void smc_wr_remove_dev(struct smc_ib_device *smcibdev);
113f38ba179SUrsula Braun void smc_wr_add_dev(struct smc_ib_device *smcibdev);
114f38ba179SUrsula Braun 
115f38ba179SUrsula Braun int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler,
116f38ba179SUrsula Braun 			    struct smc_wr_buf **wr_buf,
117ad6f317fSUrsula Braun 			    struct smc_rdma_wr **wrs,
118f38ba179SUrsula Braun 			    struct smc_wr_tx_pend_priv **wr_pend_priv);
119b4ba4652SKarsten Graul int smc_wr_tx_get_v2_slot(struct smc_link *link,
120b4ba4652SKarsten Graul 			  smc_wr_tx_handler handler,
121b4ba4652SKarsten Graul 			  struct smc_wr_v2_buf **wr_buf,
122b4ba4652SKarsten Graul 			  struct smc_wr_tx_pend_priv **wr_pend_priv);
123f38ba179SUrsula Braun int smc_wr_tx_put_slot(struct smc_link *link,
124f38ba179SUrsula Braun 		       struct smc_wr_tx_pend_priv *wr_pend_priv);
125f38ba179SUrsula Braun int smc_wr_tx_send(struct smc_link *link,
126f38ba179SUrsula Braun 		   struct smc_wr_tx_pend_priv *wr_pend_priv);
127b4ba4652SKarsten Graul int smc_wr_tx_v2_send(struct smc_link *link,
128b4ba4652SKarsten Graul 		      struct smc_wr_tx_pend_priv *priv, int len);
12909c61d24SKarsten Graul int smc_wr_tx_send_wait(struct smc_link *link, struct smc_wr_tx_pend_priv *priv,
13009c61d24SKarsten Graul 			unsigned long timeout);
131f38ba179SUrsula Braun void smc_wr_tx_cq_handler(struct ib_cq *ib_cq, void *cq_context);
132349d4312SDust Li void smc_wr_tx_wait_no_pending_sends(struct smc_link *link);
133f38ba179SUrsula Braun 
134f38ba179SUrsula Braun int smc_wr_rx_register_handler(struct smc_wr_rx_handler *handler);
135f38ba179SUrsula Braun int smc_wr_rx_post_init(struct smc_link *link);
136f38ba179SUrsula Braun void smc_wr_rx_cq_handler(struct ib_cq *ib_cq, void *cq_context);
137652a1e41SUrsula Braun int smc_wr_reg_send(struct smc_link *link, struct ib_mr *mr);
138f38ba179SUrsula Braun 
139f38ba179SUrsula Braun #endif /* SMC_WR_H */
140