Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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