Blame view
net/smc/smc_cdc.h
5.75 KB
b24413180 License cleanup: ... |
1 |
/* SPDX-License-Identifier: GPL-2.0 */ |
5f08318f6 smc: connection d... |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
/* * Shared Memory Communications over RDMA (SMC-R) and RoCE * * Connection Data Control (CDC) * * Copyright IBM Corp. 2016 * * Author(s): Ursula Braun <ubraun@linux.vnet.ibm.com> */ #ifndef SMC_CDC_H #define SMC_CDC_H #include <linux/kernel.h> /* max_t */ #include <linux/atomic.h> #include <linux/in.h> #include <linux/compiler.h> #include "smc.h" #include "smc_core.h" #include "smc_wr.h" #define SMC_CDC_MSG_TYPE 0xFE /* in network byte order */ union smc_cdc_cursor { /* SMC cursor */ struct { __be16 reserved; __be16 wrap; __be32 count; }; #ifdef KERNEL_HAS_ATOMIC64 atomic64_t acurs; /* for atomic processing */ #else u64 acurs; /* for atomic processing */ #endif } __aligned(8); /* in network byte order */ struct smc_cdc_msg { struct smc_wr_rx_hdr common; /* .type = 0xFE */ u8 len; /* 44 */ __be16 seqno; __be32 token; union smc_cdc_cursor prod; union smc_cdc_cursor cons; /* piggy backed "ack" */ struct smc_cdc_producer_flags prod_flags; struct smc_cdc_conn_state_flags conn_state_flags; u8 reserved[18]; } __aligned(8); static inline bool smc_cdc_rxed_any_close(struct smc_connection *conn) { return conn->local_rx_ctrl.conn_state_flags.peer_conn_abort || conn->local_rx_ctrl.conn_state_flags.peer_conn_closed; } static inline bool smc_cdc_rxed_any_close_or_senddone( struct smc_connection *conn) { return smc_cdc_rxed_any_close(conn) || conn->local_rx_ctrl.conn_state_flags.peer_done_writing; } static inline void smc_curs_add(int size, union smc_host_cursor *curs, int value) { curs->count += value; if (curs->count >= size) { curs->wrap++; curs->count -= size; } } /* SMC cursors are 8 bytes long and require atomic reading and writing */ static inline u64 smc_curs_read(union smc_host_cursor *curs, struct smc_connection *conn) { #ifndef KERNEL_HAS_ATOMIC64 unsigned long flags; u64 ret; spin_lock_irqsave(&conn->acurs_lock, flags); ret = curs->acurs; spin_unlock_irqrestore(&conn->acurs_lock, flags); return ret; #else return atomic64_read(&curs->acurs); #endif } static inline u64 smc_curs_read_net(union smc_cdc_cursor *curs, struct smc_connection *conn) { #ifndef KERNEL_HAS_ATOMIC64 unsigned long flags; u64 ret; spin_lock_irqsave(&conn->acurs_lock, flags); ret = curs->acurs; spin_unlock_irqrestore(&conn->acurs_lock, flags); return ret; #else return atomic64_read(&curs->acurs); #endif } static inline void smc_curs_write(union smc_host_cursor *curs, u64 val, struct smc_connection *conn) { #ifndef KERNEL_HAS_ATOMIC64 unsigned long flags; spin_lock_irqsave(&conn->acurs_lock, flags); curs->acurs = val; spin_unlock_irqrestore(&conn->acurs_lock, flags); #else atomic64_set(&curs->acurs, val); #endif } static inline void smc_curs_write_net(union smc_cdc_cursor *curs, u64 val, struct smc_connection *conn) { #ifndef KERNEL_HAS_ATOMIC64 unsigned long flags; spin_lock_irqsave(&conn->acurs_lock, flags); curs->acurs = val; spin_unlock_irqrestore(&conn->acurs_lock, flags); #else atomic64_set(&curs->acurs, val); #endif } /* calculate cursor difference between old and new, where old <= new */ static inline int smc_curs_diff(unsigned int size, union smc_host_cursor *old, union smc_host_cursor *new) { if (old->wrap != new->wrap) return max_t(int, 0, ((size - old->count) + new->count)); return max_t(int, 0, (new->count - old->count)); } static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer, union smc_host_cursor *local, struct smc_connection *conn) { union smc_host_cursor temp; smc_curs_write(&temp, smc_curs_read(local, conn), conn); peer->count = htonl(temp.count); peer->wrap = htons(temp.wrap); /* peer->reserved = htons(0); must be ensured by caller */ } static inline void smc_host_msg_to_cdc(struct smc_cdc_msg *peer, struct smc_host_cdc_msg *local, struct smc_connection *conn) { peer->common.type = local->common.type; peer->len = local->len; peer->seqno = htons(local->seqno); peer->token = htonl(local->token); smc_host_cursor_to_cdc(&peer->prod, &local->prod, conn); smc_host_cursor_to_cdc(&peer->cons, &local->cons, conn); peer->prod_flags = local->prod_flags; peer->conn_state_flags = local->conn_state_flags; } static inline void smc_cdc_cursor_to_host(union smc_host_cursor *local, union smc_cdc_cursor *peer, struct smc_connection *conn) { union smc_host_cursor temp, old; union smc_cdc_cursor net; smc_curs_write(&old, smc_curs_read(local, conn), conn); smc_curs_write_net(&net, smc_curs_read_net(peer, conn), conn); temp.count = ntohl(net.count); temp.wrap = ntohs(net.wrap); if ((old.wrap > temp.wrap) && temp.wrap) return; if ((old.wrap == temp.wrap) && (old.count > temp.count)) return; smc_curs_write(local, smc_curs_read(&temp, conn), conn); } static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local, struct smc_cdc_msg *peer, struct smc_connection *conn) { local->common.type = peer->common.type; local->len = peer->len; local->seqno = ntohs(peer->seqno); local->token = ntohl(peer->token); smc_cdc_cursor_to_host(&local->prod, &peer->prod, conn); smc_cdc_cursor_to_host(&local->cons, &peer->cons, conn); local->prod_flags = peer->prod_flags; local->conn_state_flags = peer->conn_state_flags; } struct smc_cdc_tx_pend; int smc_cdc_get_free_slot(struct smc_link *link, struct smc_wr_buf **wr_buf, struct smc_cdc_tx_pend **pend); void smc_cdc_tx_dismiss_slots(struct smc_connection *conn); int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf, struct smc_cdc_tx_pend *pend); int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn); |
b38d73247 smc: socket closi... |
216 |
bool smc_cdc_tx_has_pending(struct smc_connection *conn); |
5f08318f6 smc: connection d... |
217 218 219 |
int smc_cdc_init(void) __init; #endif /* SMC_CDC_H */ |