1e0e4b8faSGuvenc Gulce /* SPDX-License-Identifier: GPL-2.0 */ 2e0e4b8faSGuvenc Gulce /* 3e0e4b8faSGuvenc Gulce * Shared Memory Communications over RDMA (SMC-R) and RoCE 4e0e4b8faSGuvenc Gulce * 5e0e4b8faSGuvenc Gulce * Macros for SMC statistics 6e0e4b8faSGuvenc Gulce * 7e0e4b8faSGuvenc Gulce * Copyright IBM Corp. 2021 8e0e4b8faSGuvenc Gulce * 9e0e4b8faSGuvenc Gulce * Author(s): Guvenc Gulce 10e0e4b8faSGuvenc Gulce */ 11e0e4b8faSGuvenc Gulce 12e0e4b8faSGuvenc Gulce #ifndef NET_SMC_SMC_STATS_H_ 13e0e4b8faSGuvenc Gulce #define NET_SMC_SMC_STATS_H_ 14e0e4b8faSGuvenc Gulce #include <linux/init.h> 15e0e4b8faSGuvenc Gulce #include <linux/mutex.h> 16e0e4b8faSGuvenc Gulce #include <linux/percpu.h> 17e0e4b8faSGuvenc Gulce #include <linux/ctype.h> 18e0e4b8faSGuvenc Gulce #include <linux/smc.h> 19e0e4b8faSGuvenc Gulce 20e0e4b8faSGuvenc Gulce #include "smc_clc.h" 21e0e4b8faSGuvenc Gulce 22e0e4b8faSGuvenc Gulce #define SMC_MAX_FBACK_RSN_CNT 30 23e0e4b8faSGuvenc Gulce 24e0e4b8faSGuvenc Gulce extern struct smc_stats __percpu *smc_stats; /* per cpu counters for SMC */ 25e0e4b8faSGuvenc Gulce extern struct smc_stats_reason fback_rsn; 26e0e4b8faSGuvenc Gulce extern struct mutex smc_stat_fback_rsn; 27e0e4b8faSGuvenc Gulce 28e0e4b8faSGuvenc Gulce enum { 29e0e4b8faSGuvenc Gulce SMC_BUF_8K, 30e0e4b8faSGuvenc Gulce SMC_BUF_16K, 31e0e4b8faSGuvenc Gulce SMC_BUF_32K, 32e0e4b8faSGuvenc Gulce SMC_BUF_64K, 33e0e4b8faSGuvenc Gulce SMC_BUF_128K, 34e0e4b8faSGuvenc Gulce SMC_BUF_256K, 35e0e4b8faSGuvenc Gulce SMC_BUF_512K, 36e0e4b8faSGuvenc Gulce SMC_BUF_1024K, 37e0e4b8faSGuvenc Gulce SMC_BUF_G_1024K, 38e0e4b8faSGuvenc Gulce SMC_BUF_MAX, 39e0e4b8faSGuvenc Gulce }; 40e0e4b8faSGuvenc Gulce 41e0e4b8faSGuvenc Gulce struct smc_stats_fback { 42e0e4b8faSGuvenc Gulce int fback_code; 43e0e4b8faSGuvenc Gulce u16 count; 44e0e4b8faSGuvenc Gulce }; 45e0e4b8faSGuvenc Gulce 46e0e4b8faSGuvenc Gulce struct smc_stats_reason { 47e0e4b8faSGuvenc Gulce struct smc_stats_fback srv[SMC_MAX_FBACK_RSN_CNT]; 48e0e4b8faSGuvenc Gulce struct smc_stats_fback clnt[SMC_MAX_FBACK_RSN_CNT]; 49e0e4b8faSGuvenc Gulce u64 srv_fback_cnt; 50e0e4b8faSGuvenc Gulce u64 clnt_fback_cnt; 51e0e4b8faSGuvenc Gulce }; 52e0e4b8faSGuvenc Gulce 53e0e4b8faSGuvenc Gulce struct smc_stats_rmbcnt { 54e0e4b8faSGuvenc Gulce u64 buf_size_small_peer_cnt; 55e0e4b8faSGuvenc Gulce u64 buf_size_small_cnt; 56e0e4b8faSGuvenc Gulce u64 buf_full_peer_cnt; 57e0e4b8faSGuvenc Gulce u64 buf_full_cnt; 58e0e4b8faSGuvenc Gulce u64 reuse_cnt; 59e0e4b8faSGuvenc Gulce u64 alloc_cnt; 60e0e4b8faSGuvenc Gulce u64 dgrade_cnt; 61e0e4b8faSGuvenc Gulce }; 62e0e4b8faSGuvenc Gulce 63e0e4b8faSGuvenc Gulce struct smc_stats_memsize { 64e0e4b8faSGuvenc Gulce u64 buf[SMC_BUF_MAX]; 65e0e4b8faSGuvenc Gulce }; 66e0e4b8faSGuvenc Gulce 67e0e4b8faSGuvenc Gulce struct smc_stats_tech { 68e0e4b8faSGuvenc Gulce struct smc_stats_memsize tx_rmbsize; 69e0e4b8faSGuvenc Gulce struct smc_stats_memsize rx_rmbsize; 70e0e4b8faSGuvenc Gulce struct smc_stats_memsize tx_pd; 71e0e4b8faSGuvenc Gulce struct smc_stats_memsize rx_pd; 72e0e4b8faSGuvenc Gulce struct smc_stats_rmbcnt rmb_tx; 73e0e4b8faSGuvenc Gulce struct smc_stats_rmbcnt rmb_rx; 74e0e4b8faSGuvenc Gulce u64 clnt_v1_succ_cnt; 75e0e4b8faSGuvenc Gulce u64 clnt_v2_succ_cnt; 76e0e4b8faSGuvenc Gulce u64 srv_v1_succ_cnt; 77e0e4b8faSGuvenc Gulce u64 srv_v2_succ_cnt; 78e0e4b8faSGuvenc Gulce u64 sendpage_cnt; 79e0e4b8faSGuvenc Gulce u64 urg_data_cnt; 80e0e4b8faSGuvenc Gulce u64 splice_cnt; 81e0e4b8faSGuvenc Gulce u64 cork_cnt; 82e0e4b8faSGuvenc Gulce u64 ndly_cnt; 83e0e4b8faSGuvenc Gulce u64 rx_bytes; 84e0e4b8faSGuvenc Gulce u64 tx_bytes; 85e0e4b8faSGuvenc Gulce u64 rx_cnt; 86e0e4b8faSGuvenc Gulce u64 tx_cnt; 87e0e4b8faSGuvenc Gulce }; 88e0e4b8faSGuvenc Gulce 89e0e4b8faSGuvenc Gulce struct smc_stats { 90e0e4b8faSGuvenc Gulce struct smc_stats_tech smc[2]; 91e0e4b8faSGuvenc Gulce u64 clnt_hshake_err_cnt; 92e0e4b8faSGuvenc Gulce u64 srv_hshake_err_cnt; 93e0e4b8faSGuvenc Gulce }; 94e0e4b8faSGuvenc Gulce 95e0e4b8faSGuvenc Gulce #define SMC_STAT_PAYLOAD_SUB(_tech, key, _len, _rc) \ 96e0e4b8faSGuvenc Gulce do { \ 97e0e4b8faSGuvenc Gulce typeof(_tech) t = (_tech); \ 98e0e4b8faSGuvenc Gulce typeof(_len) l = (_len); \ 99e0e4b8faSGuvenc Gulce int _pos = fls64((l) >> 13); \ 100e0e4b8faSGuvenc Gulce typeof(_rc) r = (_rc); \ 101e0e4b8faSGuvenc Gulce int m = SMC_BUF_MAX - 1; \ 102e0e4b8faSGuvenc Gulce this_cpu_inc((*smc_stats).smc[t].key ## _cnt); \ 103e0e4b8faSGuvenc Gulce if (r <= 0) \ 104e0e4b8faSGuvenc Gulce break; \ 105e0e4b8faSGuvenc Gulce _pos = (_pos < m) ? ((l == 1 << (_pos + 12)) ? _pos - 1 : _pos) : m; \ 106e0e4b8faSGuvenc Gulce this_cpu_inc((*smc_stats).smc[t].key ## _pd.buf[_pos]); \ 107e0e4b8faSGuvenc Gulce this_cpu_add((*smc_stats).smc[t].key ## _bytes, r); \ 108e0e4b8faSGuvenc Gulce } \ 109e0e4b8faSGuvenc Gulce while (0) 110e0e4b8faSGuvenc Gulce 111e0e4b8faSGuvenc Gulce #define SMC_STAT_TX_PAYLOAD(_smc, length, rcode) \ 112e0e4b8faSGuvenc Gulce do { \ 113e0e4b8faSGuvenc Gulce typeof(_smc) __smc = _smc; \ 114e0e4b8faSGuvenc Gulce typeof(length) _len = (length); \ 115e0e4b8faSGuvenc Gulce typeof(rcode) _rc = (rcode); \ 116e0e4b8faSGuvenc Gulce bool is_smcd = !__smc->conn.lnk; \ 117e0e4b8faSGuvenc Gulce if (is_smcd) \ 118e0e4b8faSGuvenc Gulce SMC_STAT_PAYLOAD_SUB(SMC_TYPE_D, tx, _len, _rc); \ 119e0e4b8faSGuvenc Gulce else \ 120e0e4b8faSGuvenc Gulce SMC_STAT_PAYLOAD_SUB(SMC_TYPE_R, tx, _len, _rc); \ 121e0e4b8faSGuvenc Gulce } \ 122e0e4b8faSGuvenc Gulce while (0) 123e0e4b8faSGuvenc Gulce 124e0e4b8faSGuvenc Gulce #define SMC_STAT_RX_PAYLOAD(_smc, length, rcode) \ 125e0e4b8faSGuvenc Gulce do { \ 126e0e4b8faSGuvenc Gulce typeof(_smc) __smc = _smc; \ 127e0e4b8faSGuvenc Gulce typeof(length) _len = (length); \ 128e0e4b8faSGuvenc Gulce typeof(rcode) _rc = (rcode); \ 129e0e4b8faSGuvenc Gulce bool is_smcd = !__smc->conn.lnk; \ 130e0e4b8faSGuvenc Gulce if (is_smcd) \ 131e0e4b8faSGuvenc Gulce SMC_STAT_PAYLOAD_SUB(SMC_TYPE_D, rx, _len, _rc); \ 132e0e4b8faSGuvenc Gulce else \ 133e0e4b8faSGuvenc Gulce SMC_STAT_PAYLOAD_SUB(SMC_TYPE_R, rx, _len, _rc); \ 134e0e4b8faSGuvenc Gulce } \ 135e0e4b8faSGuvenc Gulce while (0) 136e0e4b8faSGuvenc Gulce 137e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_SIZE_SUB(_tech, k, _len) \ 138e0e4b8faSGuvenc Gulce do { \ 139e0e4b8faSGuvenc Gulce typeof(_len) _l = (_len); \ 140e0e4b8faSGuvenc Gulce typeof(_tech) t = (_tech); \ 141e0e4b8faSGuvenc Gulce int _pos = fls((_l) >> 13); \ 142e0e4b8faSGuvenc Gulce int m = SMC_BUF_MAX - 1; \ 143e0e4b8faSGuvenc Gulce _pos = (_pos < m) ? ((_l == 1 << (_pos + 12)) ? _pos - 1 : _pos) : m; \ 144e0e4b8faSGuvenc Gulce this_cpu_inc((*smc_stats).smc[t].k ## _rmbsize.buf[_pos]); \ 145e0e4b8faSGuvenc Gulce } \ 146e0e4b8faSGuvenc Gulce while (0) 147e0e4b8faSGuvenc Gulce 148e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_SUB(type, t, key) \ 149e0e4b8faSGuvenc Gulce this_cpu_inc((*smc_stats).smc[t].rmb ## _ ## key.type ## _cnt) 150e0e4b8faSGuvenc Gulce 151e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_SIZE(_is_smcd, _is_rx, _len) \ 152e0e4b8faSGuvenc Gulce do { \ 153e0e4b8faSGuvenc Gulce typeof(_is_smcd) is_d = (_is_smcd); \ 154e0e4b8faSGuvenc Gulce typeof(_is_rx) is_r = (_is_rx); \ 155e0e4b8faSGuvenc Gulce typeof(_len) l = (_len); \ 156e0e4b8faSGuvenc Gulce if ((is_d) && (is_r)) \ 157e0e4b8faSGuvenc Gulce SMC_STAT_RMB_SIZE_SUB(SMC_TYPE_D, rx, l); \ 158e0e4b8faSGuvenc Gulce if ((is_d) && !(is_r)) \ 159e0e4b8faSGuvenc Gulce SMC_STAT_RMB_SIZE_SUB(SMC_TYPE_D, tx, l); \ 160e0e4b8faSGuvenc Gulce if (!(is_d) && (is_r)) \ 161e0e4b8faSGuvenc Gulce SMC_STAT_RMB_SIZE_SUB(SMC_TYPE_R, rx, l); \ 162e0e4b8faSGuvenc Gulce if (!(is_d) && !(is_r)) \ 163e0e4b8faSGuvenc Gulce SMC_STAT_RMB_SIZE_SUB(SMC_TYPE_R, tx, l); \ 164e0e4b8faSGuvenc Gulce } \ 165e0e4b8faSGuvenc Gulce while (0) 166e0e4b8faSGuvenc Gulce 167e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB(type, _is_smcd, _is_rx) \ 168e0e4b8faSGuvenc Gulce do { \ 169e0e4b8faSGuvenc Gulce typeof(_is_smcd) is_d = (_is_smcd); \ 170e0e4b8faSGuvenc Gulce typeof(_is_rx) is_r = (_is_rx); \ 171e0e4b8faSGuvenc Gulce if ((is_d) && (is_r)) \ 172e0e4b8faSGuvenc Gulce SMC_STAT_RMB_SUB(type, SMC_TYPE_D, rx); \ 173e0e4b8faSGuvenc Gulce if ((is_d) && !(is_r)) \ 174e0e4b8faSGuvenc Gulce SMC_STAT_RMB_SUB(type, SMC_TYPE_D, tx); \ 175e0e4b8faSGuvenc Gulce if (!(is_d) && (is_r)) \ 176e0e4b8faSGuvenc Gulce SMC_STAT_RMB_SUB(type, SMC_TYPE_R, rx); \ 177e0e4b8faSGuvenc Gulce if (!(is_d) && !(is_r)) \ 178e0e4b8faSGuvenc Gulce SMC_STAT_RMB_SUB(type, SMC_TYPE_R, tx); \ 179e0e4b8faSGuvenc Gulce } \ 180e0e4b8faSGuvenc Gulce while (0) 181e0e4b8faSGuvenc Gulce 182e0e4b8faSGuvenc Gulce #define SMC_STAT_BUF_REUSE(is_smcd, is_rx) \ 183e0e4b8faSGuvenc Gulce SMC_STAT_RMB(reuse, is_smcd, is_rx) 184e0e4b8faSGuvenc Gulce 185e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_ALLOC(is_smcd, is_rx) \ 186e0e4b8faSGuvenc Gulce SMC_STAT_RMB(alloc, is_smcd, is_rx) 187e0e4b8faSGuvenc Gulce 188e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_DOWNGRADED(is_smcd, is_rx) \ 189e0e4b8faSGuvenc Gulce SMC_STAT_RMB(dgrade, is_smcd, is_rx) 190e0e4b8faSGuvenc Gulce 191e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_TX_PEER_FULL(is_smcd) \ 192e0e4b8faSGuvenc Gulce SMC_STAT_RMB(buf_full_peer, is_smcd, false) 193e0e4b8faSGuvenc Gulce 194e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_TX_FULL(is_smcd) \ 195e0e4b8faSGuvenc Gulce SMC_STAT_RMB(buf_full, is_smcd, false) 196e0e4b8faSGuvenc Gulce 197e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_TX_PEER_SIZE_SMALL(is_smcd) \ 198e0e4b8faSGuvenc Gulce SMC_STAT_RMB(buf_size_small_peer, is_smcd, false) 199e0e4b8faSGuvenc Gulce 200e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_TX_SIZE_SMALL(is_smcd) \ 201e0e4b8faSGuvenc Gulce SMC_STAT_RMB(buf_size_small, is_smcd, false) 202e0e4b8faSGuvenc Gulce 203e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_RX_SIZE_SMALL(is_smcd) \ 204e0e4b8faSGuvenc Gulce SMC_STAT_RMB(buf_size_small, is_smcd, true) 205e0e4b8faSGuvenc Gulce 206e0e4b8faSGuvenc Gulce #define SMC_STAT_RMB_RX_FULL(is_smcd) \ 207e0e4b8faSGuvenc Gulce SMC_STAT_RMB(buf_full, is_smcd, true) 208e0e4b8faSGuvenc Gulce 209e0e4b8faSGuvenc Gulce #define SMC_STAT_INC(is_smcd, type) \ 210e0e4b8faSGuvenc Gulce do { \ 211e0e4b8faSGuvenc Gulce if ((is_smcd)) \ 212e0e4b8faSGuvenc Gulce this_cpu_inc(smc_stats->smc[SMC_TYPE_D].type); \ 213e0e4b8faSGuvenc Gulce else \ 214e0e4b8faSGuvenc Gulce this_cpu_inc(smc_stats->smc[SMC_TYPE_R].type); \ 215e0e4b8faSGuvenc Gulce } \ 216e0e4b8faSGuvenc Gulce while (0) 217e0e4b8faSGuvenc Gulce 218e0e4b8faSGuvenc Gulce #define SMC_STAT_CLNT_SUCC_INC(_aclc) \ 219e0e4b8faSGuvenc Gulce do { \ 220e0e4b8faSGuvenc Gulce typeof(_aclc) acl = (_aclc); \ 221e0e4b8faSGuvenc Gulce bool is_v2 = (acl->hdr.version == SMC_V2); \ 222e0e4b8faSGuvenc Gulce bool is_smcd = (acl->hdr.typev1 == SMC_TYPE_D); \ 223e0e4b8faSGuvenc Gulce if (is_v2 && is_smcd) \ 224e0e4b8faSGuvenc Gulce this_cpu_inc(smc_stats->smc[SMC_TYPE_D].clnt_v2_succ_cnt); \ 225e0e4b8faSGuvenc Gulce else if (is_v2 && !is_smcd) \ 226e0e4b8faSGuvenc Gulce this_cpu_inc(smc_stats->smc[SMC_TYPE_R].clnt_v2_succ_cnt); \ 227e0e4b8faSGuvenc Gulce else if (!is_v2 && is_smcd) \ 228e0e4b8faSGuvenc Gulce this_cpu_inc(smc_stats->smc[SMC_TYPE_D].clnt_v1_succ_cnt); \ 229e0e4b8faSGuvenc Gulce else if (!is_v2 && !is_smcd) \ 230e0e4b8faSGuvenc Gulce this_cpu_inc(smc_stats->smc[SMC_TYPE_R].clnt_v1_succ_cnt); \ 231e0e4b8faSGuvenc Gulce } \ 232e0e4b8faSGuvenc Gulce while (0) 233e0e4b8faSGuvenc Gulce 234e0e4b8faSGuvenc Gulce #define SMC_STAT_SERV_SUCC_INC(_ini) \ 235e0e4b8faSGuvenc Gulce do { \ 236e0e4b8faSGuvenc Gulce typeof(_ini) i = (_ini); \ 237e0e4b8faSGuvenc Gulce bool is_v2 = (i->smcd_version & SMC_V2); \ 238e0e4b8faSGuvenc Gulce bool is_smcd = (i->is_smcd); \ 239e0e4b8faSGuvenc Gulce if (is_v2 && is_smcd) \ 240e0e4b8faSGuvenc Gulce this_cpu_inc(smc_stats->smc[SMC_TYPE_D].srv_v2_succ_cnt); \ 241e0e4b8faSGuvenc Gulce else if (is_v2 && !is_smcd) \ 242e0e4b8faSGuvenc Gulce this_cpu_inc(smc_stats->smc[SMC_TYPE_R].srv_v2_succ_cnt); \ 243e0e4b8faSGuvenc Gulce else if (!is_v2 && is_smcd) \ 244e0e4b8faSGuvenc Gulce this_cpu_inc(smc_stats->smc[SMC_TYPE_D].srv_v1_succ_cnt); \ 245e0e4b8faSGuvenc Gulce else if (!is_v2 && !is_smcd) \ 246e0e4b8faSGuvenc Gulce this_cpu_inc(smc_stats->smc[SMC_TYPE_R].srv_v1_succ_cnt); \ 247e0e4b8faSGuvenc Gulce } \ 248e0e4b8faSGuvenc Gulce while (0) 249e0e4b8faSGuvenc Gulce 250*8c40602bSGuvenc Gulce int smc_nl_get_stats(struct sk_buff *skb, struct netlink_callback *cb); 251e0e4b8faSGuvenc Gulce int smc_stats_init(void) __init; 252e0e4b8faSGuvenc Gulce void smc_stats_exit(void); 253e0e4b8faSGuvenc Gulce 254e0e4b8faSGuvenc Gulce #endif /* NET_SMC_SMC_STATS_H_ */ 255