| .. | .. |
|---|
| 48 | 48 | struct smc_cdc_producer_flags prod_flags; |
|---|
| 49 | 49 | struct smc_cdc_conn_state_flags conn_state_flags; |
|---|
| 50 | 50 | u8 reserved[18]; |
|---|
| 51 | | -} __packed; /* format defined in RFC7609 */ |
|---|
| 51 | +}; |
|---|
| 52 | + |
|---|
| 53 | +/* SMC-D cursor format */ |
|---|
| 54 | +union smcd_cdc_cursor { |
|---|
| 55 | + struct { |
|---|
| 56 | + u16 wrap; |
|---|
| 57 | + u32 count; |
|---|
| 58 | + struct smc_cdc_producer_flags prod_flags; |
|---|
| 59 | + struct smc_cdc_conn_state_flags conn_state_flags; |
|---|
| 60 | + } __packed; |
|---|
| 61 | +#ifdef KERNEL_HAS_ATOMIC64 |
|---|
| 62 | + atomic64_t acurs; /* for atomic processing */ |
|---|
| 63 | +#else |
|---|
| 64 | + u64 acurs; /* for atomic processing */ |
|---|
| 65 | +#endif |
|---|
| 66 | +} __aligned(8); |
|---|
| 52 | 67 | |
|---|
| 53 | 68 | /* CDC message for SMC-D */ |
|---|
| 54 | 69 | struct smcd_cdc_msg { |
|---|
| 55 | 70 | struct smc_wr_rx_hdr common; /* Type = 0xFE */ |
|---|
| 56 | 71 | u8 res1[7]; |
|---|
| 57 | | - u16 prod_wrap; |
|---|
| 58 | | - u32 prod_count; |
|---|
| 59 | | - u8 res2[2]; |
|---|
| 60 | | - u16 cons_wrap; |
|---|
| 61 | | - u32 cons_count; |
|---|
| 62 | | - struct smc_cdc_producer_flags prod_flags; |
|---|
| 63 | | - struct smc_cdc_conn_state_flags conn_state_flags; |
|---|
| 72 | + union smcd_cdc_cursor prod; |
|---|
| 73 | + union smcd_cdc_cursor cons; |
|---|
| 64 | 74 | u8 res3[8]; |
|---|
| 65 | | -} __packed; |
|---|
| 75 | +} __aligned(8); |
|---|
| 66 | 76 | |
|---|
| 67 | 77 | static inline bool smc_cdc_rxed_any_close(struct smc_connection *conn) |
|---|
| 68 | 78 | { |
|---|
| .. | .. |
|---|
| 87 | 97 | } |
|---|
| 88 | 98 | } |
|---|
| 89 | 99 | |
|---|
| 90 | | -/* SMC cursors are 8 bytes long and require atomic reading and writing */ |
|---|
| 91 | | -static inline u64 smc_curs_read(union smc_host_cursor *curs, |
|---|
| 92 | | - struct smc_connection *conn) |
|---|
| 93 | | -{ |
|---|
| 94 | | -#ifndef KERNEL_HAS_ATOMIC64 |
|---|
| 95 | | - unsigned long flags; |
|---|
| 96 | | - u64 ret; |
|---|
| 97 | | - |
|---|
| 98 | | - spin_lock_irqsave(&conn->acurs_lock, flags); |
|---|
| 99 | | - ret = curs->acurs; |
|---|
| 100 | | - spin_unlock_irqrestore(&conn->acurs_lock, flags); |
|---|
| 101 | | - return ret; |
|---|
| 102 | | -#else |
|---|
| 103 | | - return atomic64_read(&curs->acurs); |
|---|
| 104 | | -#endif |
|---|
| 105 | | -} |
|---|
| 106 | | - |
|---|
| 107 | 100 | /* Copy cursor src into tgt */ |
|---|
| 108 | 101 | static inline void smc_curs_copy(union smc_host_cursor *tgt, |
|---|
| 109 | 102 | union smc_host_cursor *src, |
|---|
| .. | .. |
|---|
| 123 | 116 | static inline void smc_curs_copy_net(union smc_cdc_cursor *tgt, |
|---|
| 124 | 117 | union smc_cdc_cursor *src, |
|---|
| 125 | 118 | struct smc_connection *conn) |
|---|
| 119 | +{ |
|---|
| 120 | +#ifndef KERNEL_HAS_ATOMIC64 |
|---|
| 121 | + unsigned long flags; |
|---|
| 122 | + |
|---|
| 123 | + spin_lock_irqsave(&conn->acurs_lock, flags); |
|---|
| 124 | + tgt->acurs = src->acurs; |
|---|
| 125 | + spin_unlock_irqrestore(&conn->acurs_lock, flags); |
|---|
| 126 | +#else |
|---|
| 127 | + atomic64_set(&tgt->acurs, atomic64_read(&src->acurs)); |
|---|
| 128 | +#endif |
|---|
| 129 | +} |
|---|
| 130 | + |
|---|
| 131 | +static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt, |
|---|
| 132 | + union smcd_cdc_cursor *src, |
|---|
| 133 | + struct smc_connection *conn) |
|---|
| 126 | 134 | { |
|---|
| 127 | 135 | #ifndef KERNEL_HAS_ATOMIC64 |
|---|
| 128 | 136 | unsigned long flags; |
|---|
| .. | .. |
|---|
| 245 | 253 | } |
|---|
| 246 | 254 | |
|---|
| 247 | 255 | static inline void smcd_cdc_msg_to_host(struct smc_host_cdc_msg *local, |
|---|
| 248 | | - struct smcd_cdc_msg *peer) |
|---|
| 256 | + struct smcd_cdc_msg *peer, |
|---|
| 257 | + struct smc_connection *conn) |
|---|
| 249 | 258 | { |
|---|
| 250 | | - local->prod.wrap = peer->prod_wrap; |
|---|
| 251 | | - local->prod.count = peer->prod_count; |
|---|
| 252 | | - local->cons.wrap = peer->cons_wrap; |
|---|
| 253 | | - local->cons.count = peer->cons_count; |
|---|
| 254 | | - local->prod_flags = peer->prod_flags; |
|---|
| 255 | | - local->conn_state_flags = peer->conn_state_flags; |
|---|
| 259 | + union smc_host_cursor temp; |
|---|
| 260 | + |
|---|
| 261 | + temp.wrap = peer->prod.wrap; |
|---|
| 262 | + temp.count = peer->prod.count; |
|---|
| 263 | + smc_curs_copy(&local->prod, &temp, conn); |
|---|
| 264 | + |
|---|
| 265 | + temp.wrap = peer->cons.wrap; |
|---|
| 266 | + temp.count = peer->cons.count; |
|---|
| 267 | + smc_curs_copy(&local->cons, &temp, conn); |
|---|
| 268 | + local->prod_flags = peer->cons.prod_flags; |
|---|
| 269 | + local->conn_state_flags = peer->cons.conn_state_flags; |
|---|
| 256 | 270 | } |
|---|
| 257 | 271 | |
|---|
| 258 | 272 | static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local, |
|---|
| .. | .. |
|---|
| 260 | 274 | struct smc_connection *conn) |
|---|
| 261 | 275 | { |
|---|
| 262 | 276 | if (conn->lgr->is_smcd) |
|---|
| 263 | | - smcd_cdc_msg_to_host(local, (struct smcd_cdc_msg *)peer); |
|---|
| 277 | + smcd_cdc_msg_to_host(local, (struct smcd_cdc_msg *)peer, conn); |
|---|
| 264 | 278 | else |
|---|
| 265 | 279 | smcr_cdc_msg_to_host(local, peer, conn); |
|---|
| 266 | 280 | } |
|---|
| 267 | 281 | |
|---|
| 268 | | -struct smc_cdc_tx_pend; |
|---|
| 282 | +struct smc_cdc_tx_pend { |
|---|
| 283 | + struct smc_connection *conn; /* socket connection */ |
|---|
| 284 | + union smc_host_cursor cursor; /* tx sndbuf cursor sent */ |
|---|
| 285 | + union smc_host_cursor p_cursor; /* rx RMBE cursor produced */ |
|---|
| 286 | + u16 ctrl_seq; /* conn. tx sequence # */ |
|---|
| 287 | +}; |
|---|
| 269 | 288 | |
|---|
| 270 | 289 | int smc_cdc_get_free_slot(struct smc_connection *conn, |
|---|
| 290 | + struct smc_link *link, |
|---|
| 271 | 291 | struct smc_wr_buf **wr_buf, |
|---|
| 292 | + struct smc_rdma_wr **wr_rdma_buf, |
|---|
| 272 | 293 | struct smc_cdc_tx_pend **pend); |
|---|
| 273 | | -void smc_cdc_tx_dismiss_slots(struct smc_connection *conn); |
|---|
| 294 | +void smc_cdc_wait_pend_tx_wr(struct smc_connection *conn); |
|---|
| 274 | 295 | int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf, |
|---|
| 275 | 296 | struct smc_cdc_tx_pend *pend); |
|---|
| 276 | 297 | int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn); |
|---|
| 277 | 298 | int smcd_cdc_msg_send(struct smc_connection *conn); |
|---|
| 299 | +int smcr_cdc_msg_send_validation(struct smc_connection *conn, |
|---|
| 300 | + struct smc_cdc_tx_pend *pend, |
|---|
| 301 | + struct smc_wr_buf *wr_buf); |
|---|
| 278 | 302 | int smc_cdc_init(void) __init; |
|---|
| 279 | 303 | void smcd_cdc_rx_init(struct smc_connection *conn); |
|---|
| 280 | 304 | |
|---|