1*25730d8bSEdward Cree // SPDX-License-Identifier: GPL-2.0-only 2*25730d8bSEdward Cree /**************************************************************************** 3*25730d8bSEdward Cree * Driver for Solarflare network controllers and boards 4*25730d8bSEdward Cree * Copyright 2022 Advanced Micro Devices, Inc. 5*25730d8bSEdward Cree * 6*25730d8bSEdward Cree * This program is free software; you can redistribute it and/or modify it 7*25730d8bSEdward Cree * under the terms of the GNU General Public License version 2 as published 8*25730d8bSEdward Cree * by the Free Software Foundation, incorporated herein by reference. 9*25730d8bSEdward Cree */ 10*25730d8bSEdward Cree 11*25730d8bSEdward Cree #include "tc_counters.h" 12*25730d8bSEdward Cree #include "mae_counter_format.h" 13*25730d8bSEdward Cree #include "mae.h" 14*25730d8bSEdward Cree #include "rx_common.h" 15*25730d8bSEdward Cree 16*25730d8bSEdward Cree /* TC Channel. Counter updates are delivered on this channel's RXQ. */ 17*25730d8bSEdward Cree 18*25730d8bSEdward Cree static void efx_tc_handle_no_channel(struct efx_nic *efx) 19*25730d8bSEdward Cree { 20*25730d8bSEdward Cree netif_warn(efx, drv, efx->net_dev, 21*25730d8bSEdward Cree "MAE counters require MSI-X and 1 additional interrupt vector.\n"); 22*25730d8bSEdward Cree } 23*25730d8bSEdward Cree 24*25730d8bSEdward Cree static int efx_tc_probe_channel(struct efx_channel *channel) 25*25730d8bSEdward Cree { 26*25730d8bSEdward Cree struct efx_rx_queue *rx_queue = &channel->rx_queue; 27*25730d8bSEdward Cree 28*25730d8bSEdward Cree channel->irq_moderation_us = 0; 29*25730d8bSEdward Cree rx_queue->core_index = 0; 30*25730d8bSEdward Cree 31*25730d8bSEdward Cree INIT_WORK(&rx_queue->grant_work, efx_mae_counters_grant_credits); 32*25730d8bSEdward Cree 33*25730d8bSEdward Cree return 0; 34*25730d8bSEdward Cree } 35*25730d8bSEdward Cree 36*25730d8bSEdward Cree static int efx_tc_start_channel(struct efx_channel *channel) 37*25730d8bSEdward Cree { 38*25730d8bSEdward Cree struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel); 39*25730d8bSEdward Cree struct efx_nic *efx = channel->efx; 40*25730d8bSEdward Cree 41*25730d8bSEdward Cree return efx_mae_start_counters(efx, rx_queue); 42*25730d8bSEdward Cree } 43*25730d8bSEdward Cree 44*25730d8bSEdward Cree static void efx_tc_stop_channel(struct efx_channel *channel) 45*25730d8bSEdward Cree { 46*25730d8bSEdward Cree struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel); 47*25730d8bSEdward Cree struct efx_nic *efx = channel->efx; 48*25730d8bSEdward Cree int rc; 49*25730d8bSEdward Cree 50*25730d8bSEdward Cree rc = efx_mae_stop_counters(efx, rx_queue); 51*25730d8bSEdward Cree if (rc) 52*25730d8bSEdward Cree netif_warn(efx, drv, efx->net_dev, 53*25730d8bSEdward Cree "Failed to stop MAE counters streaming, rc=%d.\n", 54*25730d8bSEdward Cree rc); 55*25730d8bSEdward Cree rx_queue->grant_credits = false; 56*25730d8bSEdward Cree flush_work(&rx_queue->grant_work); 57*25730d8bSEdward Cree } 58*25730d8bSEdward Cree 59*25730d8bSEdward Cree static void efx_tc_remove_channel(struct efx_channel *channel) 60*25730d8bSEdward Cree { 61*25730d8bSEdward Cree } 62*25730d8bSEdward Cree 63*25730d8bSEdward Cree static void efx_tc_get_channel_name(struct efx_channel *channel, 64*25730d8bSEdward Cree char *buf, size_t len) 65*25730d8bSEdward Cree { 66*25730d8bSEdward Cree snprintf(buf, len, "%s-mae", channel->efx->name); 67*25730d8bSEdward Cree } 68*25730d8bSEdward Cree 69*25730d8bSEdward Cree static void efx_tc_counter_update(struct efx_nic *efx, 70*25730d8bSEdward Cree enum efx_tc_counter_type counter_type, 71*25730d8bSEdward Cree u32 counter_idx, u64 packets, u64 bytes, 72*25730d8bSEdward Cree u32 mark) 73*25730d8bSEdward Cree { 74*25730d8bSEdward Cree /* Software counter objects do not exist yet, for now we ignore this */ 75*25730d8bSEdward Cree } 76*25730d8bSEdward Cree 77*25730d8bSEdward Cree static void efx_tc_rx_version_1(struct efx_nic *efx, const u8 *data, u32 mark) 78*25730d8bSEdward Cree { 79*25730d8bSEdward Cree u16 n_counters, i; 80*25730d8bSEdward Cree 81*25730d8bSEdward Cree /* Header format: 82*25730d8bSEdward Cree * + | 0 | 1 | 2 | 3 | 83*25730d8bSEdward Cree * 0 |version | reserved | 84*25730d8bSEdward Cree * 4 | seq_index | n_counters | 85*25730d8bSEdward Cree */ 86*25730d8bSEdward Cree 87*25730d8bSEdward Cree n_counters = le16_to_cpu(*(const __le16 *)(data + 6)); 88*25730d8bSEdward Cree 89*25730d8bSEdward Cree /* Counter update entry format: 90*25730d8bSEdward Cree * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | 91*25730d8bSEdward Cree * | counter_idx | packet_count | byte_count | 92*25730d8bSEdward Cree */ 93*25730d8bSEdward Cree for (i = 0; i < n_counters; i++) { 94*25730d8bSEdward Cree const void *entry = data + 8 + 16 * i; 95*25730d8bSEdward Cree u64 packet_count, byte_count; 96*25730d8bSEdward Cree u32 counter_idx; 97*25730d8bSEdward Cree 98*25730d8bSEdward Cree counter_idx = le32_to_cpu(*(const __le32 *)entry); 99*25730d8bSEdward Cree packet_count = le32_to_cpu(*(const __le32 *)(entry + 4)) | 100*25730d8bSEdward Cree ((u64)le16_to_cpu(*(const __le16 *)(entry + 8)) << 32); 101*25730d8bSEdward Cree byte_count = le16_to_cpu(*(const __le16 *)(entry + 10)) | 102*25730d8bSEdward Cree ((u64)le32_to_cpu(*(const __le32 *)(entry + 12)) << 16); 103*25730d8bSEdward Cree efx_tc_counter_update(efx, EFX_TC_COUNTER_TYPE_AR, counter_idx, 104*25730d8bSEdward Cree packet_count, byte_count, mark); 105*25730d8bSEdward Cree } 106*25730d8bSEdward Cree } 107*25730d8bSEdward Cree 108*25730d8bSEdward Cree #define TCV2_HDR_PTR(pkt, field) \ 109*25730d8bSEdward Cree ((void)BUILD_BUG_ON_ZERO(ERF_SC_PACKETISER_HEADER_##field##_LBN & 7), \ 110*25730d8bSEdward Cree (pkt) + ERF_SC_PACKETISER_HEADER_##field##_LBN / 8) 111*25730d8bSEdward Cree #define TCV2_HDR_BYTE(pkt, field) \ 112*25730d8bSEdward Cree ((void)BUILD_BUG_ON_ZERO(ERF_SC_PACKETISER_HEADER_##field##_WIDTH != 8),\ 113*25730d8bSEdward Cree *TCV2_HDR_PTR(pkt, field)) 114*25730d8bSEdward Cree #define TCV2_HDR_WORD(pkt, field) \ 115*25730d8bSEdward Cree ((void)BUILD_BUG_ON_ZERO(ERF_SC_PACKETISER_HEADER_##field##_WIDTH != 16),\ 116*25730d8bSEdward Cree (void)BUILD_BUG_ON_ZERO(ERF_SC_PACKETISER_HEADER_##field##_LBN & 15), \ 117*25730d8bSEdward Cree *(__force const __le16 *)TCV2_HDR_PTR(pkt, field)) 118*25730d8bSEdward Cree #define TCV2_PKT_PTR(pkt, poff, i, field) \ 119*25730d8bSEdward Cree ((void)BUILD_BUG_ON_ZERO(ERF_SC_PACKETISER_PAYLOAD_##field##_LBN & 7), \ 120*25730d8bSEdward Cree (pkt) + ERF_SC_PACKETISER_PAYLOAD_##field##_LBN/8 + poff + \ 121*25730d8bSEdward Cree i * ER_RX_SL_PACKETISER_PAYLOAD_WORD_SIZE) 122*25730d8bSEdward Cree 123*25730d8bSEdward Cree /* Read a little-endian 48-bit field with 16-bit alignment */ 124*25730d8bSEdward Cree static u64 efx_tc_read48(const __le16 *field) 125*25730d8bSEdward Cree { 126*25730d8bSEdward Cree u64 out = 0; 127*25730d8bSEdward Cree int i; 128*25730d8bSEdward Cree 129*25730d8bSEdward Cree for (i = 0; i < 3; i++) 130*25730d8bSEdward Cree out |= (u64)le16_to_cpu(field[i]) << (i * 16); 131*25730d8bSEdward Cree return out; 132*25730d8bSEdward Cree } 133*25730d8bSEdward Cree 134*25730d8bSEdward Cree static enum efx_tc_counter_type efx_tc_rx_version_2(struct efx_nic *efx, 135*25730d8bSEdward Cree const u8 *data, u32 mark) 136*25730d8bSEdward Cree { 137*25730d8bSEdward Cree u8 payload_offset, header_offset, ident; 138*25730d8bSEdward Cree enum efx_tc_counter_type type; 139*25730d8bSEdward Cree u16 n_counters, i; 140*25730d8bSEdward Cree 141*25730d8bSEdward Cree ident = TCV2_HDR_BYTE(data, IDENTIFIER); 142*25730d8bSEdward Cree switch (ident) { 143*25730d8bSEdward Cree case ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR: 144*25730d8bSEdward Cree type = EFX_TC_COUNTER_TYPE_AR; 145*25730d8bSEdward Cree break; 146*25730d8bSEdward Cree case ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT: 147*25730d8bSEdward Cree type = EFX_TC_COUNTER_TYPE_CT; 148*25730d8bSEdward Cree break; 149*25730d8bSEdward Cree case ERF_SC_PACKETISER_HEADER_IDENTIFIER_OR: 150*25730d8bSEdward Cree type = EFX_TC_COUNTER_TYPE_OR; 151*25730d8bSEdward Cree break; 152*25730d8bSEdward Cree default: 153*25730d8bSEdward Cree if (net_ratelimit()) 154*25730d8bSEdward Cree netif_err(efx, drv, efx->net_dev, 155*25730d8bSEdward Cree "ignored v2 MAE counter packet (bad identifier %u" 156*25730d8bSEdward Cree "), counters may be inaccurate\n", ident); 157*25730d8bSEdward Cree return EFX_TC_COUNTER_TYPE_MAX; 158*25730d8bSEdward Cree } 159*25730d8bSEdward Cree header_offset = TCV2_HDR_BYTE(data, HEADER_OFFSET); 160*25730d8bSEdward Cree /* mae_counter_format.h implies that this offset is fixed, since it 161*25730d8bSEdward Cree * carries on with SOP-based LBNs for the fields in this header 162*25730d8bSEdward Cree */ 163*25730d8bSEdward Cree if (header_offset != ERF_SC_PACKETISER_HEADER_HEADER_OFFSET_DEFAULT) { 164*25730d8bSEdward Cree if (net_ratelimit()) 165*25730d8bSEdward Cree netif_err(efx, drv, efx->net_dev, 166*25730d8bSEdward Cree "choked on v2 MAE counter packet (bad header_offset %u" 167*25730d8bSEdward Cree "), counters may be inaccurate\n", header_offset); 168*25730d8bSEdward Cree return EFX_TC_COUNTER_TYPE_MAX; 169*25730d8bSEdward Cree } 170*25730d8bSEdward Cree payload_offset = TCV2_HDR_BYTE(data, PAYLOAD_OFFSET); 171*25730d8bSEdward Cree n_counters = le16_to_cpu(TCV2_HDR_WORD(data, COUNT)); 172*25730d8bSEdward Cree 173*25730d8bSEdward Cree for (i = 0; i < n_counters; i++) { 174*25730d8bSEdward Cree const void *counter_idx_p, *packet_count_p, *byte_count_p; 175*25730d8bSEdward Cree u64 packet_count, byte_count; 176*25730d8bSEdward Cree u32 counter_idx; 177*25730d8bSEdward Cree 178*25730d8bSEdward Cree /* 24-bit field with 32-bit alignment */ 179*25730d8bSEdward Cree counter_idx_p = TCV2_PKT_PTR(data, payload_offset, i, COUNTER_INDEX); 180*25730d8bSEdward Cree BUILD_BUG_ON(ERF_SC_PACKETISER_PAYLOAD_COUNTER_INDEX_WIDTH != 24); 181*25730d8bSEdward Cree BUILD_BUG_ON(ERF_SC_PACKETISER_PAYLOAD_COUNTER_INDEX_LBN & 31); 182*25730d8bSEdward Cree counter_idx = le32_to_cpu(*(const __le32 *)counter_idx_p) & 0xffffff; 183*25730d8bSEdward Cree /* 48-bit field with 16-bit alignment */ 184*25730d8bSEdward Cree packet_count_p = TCV2_PKT_PTR(data, payload_offset, i, PACKET_COUNT); 185*25730d8bSEdward Cree BUILD_BUG_ON(ERF_SC_PACKETISER_PAYLOAD_PACKET_COUNT_WIDTH != 48); 186*25730d8bSEdward Cree BUILD_BUG_ON(ERF_SC_PACKETISER_PAYLOAD_PACKET_COUNT_LBN & 15); 187*25730d8bSEdward Cree packet_count = efx_tc_read48((const __le16 *)packet_count_p); 188*25730d8bSEdward Cree /* 48-bit field with 16-bit alignment */ 189*25730d8bSEdward Cree byte_count_p = TCV2_PKT_PTR(data, payload_offset, i, BYTE_COUNT); 190*25730d8bSEdward Cree BUILD_BUG_ON(ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_WIDTH != 48); 191*25730d8bSEdward Cree BUILD_BUG_ON(ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_LBN & 15); 192*25730d8bSEdward Cree byte_count = efx_tc_read48((const __le16 *)byte_count_p); 193*25730d8bSEdward Cree 194*25730d8bSEdward Cree if (type == EFX_TC_COUNTER_TYPE_CT) { 195*25730d8bSEdward Cree /* CT counters are 1-bit saturating counters to update 196*25730d8bSEdward Cree * the lastuse time in CT stats. A received CT counter 197*25730d8bSEdward Cree * should have packet counter to 0 and only LSB bit on 198*25730d8bSEdward Cree * in byte counter. 199*25730d8bSEdward Cree */ 200*25730d8bSEdward Cree if (packet_count || byte_count != 1) 201*25730d8bSEdward Cree netdev_warn_once(efx->net_dev, 202*25730d8bSEdward Cree "CT counter with inconsistent state (%llu, %llu)\n", 203*25730d8bSEdward Cree packet_count, byte_count); 204*25730d8bSEdward Cree /* Do not increment the driver's byte counter */ 205*25730d8bSEdward Cree byte_count = 0; 206*25730d8bSEdward Cree } 207*25730d8bSEdward Cree 208*25730d8bSEdward Cree efx_tc_counter_update(efx, type, counter_idx, packet_count, 209*25730d8bSEdward Cree byte_count, mark); 210*25730d8bSEdward Cree } 211*25730d8bSEdward Cree return type; 212*25730d8bSEdward Cree } 213*25730d8bSEdward Cree 214*25730d8bSEdward Cree /* We always swallow the packet, whether successful or not, since it's not 215*25730d8bSEdward Cree * a network packet and shouldn't ever be forwarded to the stack. 216*25730d8bSEdward Cree * @mark is the generation count for counter allocations. 217*25730d8bSEdward Cree */ 218*25730d8bSEdward Cree static bool efx_tc_rx(struct efx_rx_queue *rx_queue, u32 mark) 219*25730d8bSEdward Cree { 220*25730d8bSEdward Cree struct efx_channel *channel = efx_rx_queue_channel(rx_queue); 221*25730d8bSEdward Cree struct efx_rx_buffer *rx_buf = efx_rx_buffer(rx_queue, 222*25730d8bSEdward Cree channel->rx_pkt_index); 223*25730d8bSEdward Cree const u8 *data = efx_rx_buf_va(rx_buf); 224*25730d8bSEdward Cree struct efx_nic *efx = rx_queue->efx; 225*25730d8bSEdward Cree enum efx_tc_counter_type type; 226*25730d8bSEdward Cree u8 version; 227*25730d8bSEdward Cree 228*25730d8bSEdward Cree /* version is always first byte of packet */ 229*25730d8bSEdward Cree version = *data; 230*25730d8bSEdward Cree switch (version) { 231*25730d8bSEdward Cree case 1: 232*25730d8bSEdward Cree type = EFX_TC_COUNTER_TYPE_AR; 233*25730d8bSEdward Cree efx_tc_rx_version_1(efx, data, mark); 234*25730d8bSEdward Cree break; 235*25730d8bSEdward Cree case ERF_SC_PACKETISER_HEADER_VERSION_VALUE: // 2 236*25730d8bSEdward Cree type = efx_tc_rx_version_2(efx, data, mark); 237*25730d8bSEdward Cree break; 238*25730d8bSEdward Cree default: 239*25730d8bSEdward Cree if (net_ratelimit()) 240*25730d8bSEdward Cree netif_err(efx, drv, efx->net_dev, 241*25730d8bSEdward Cree "choked on MAE counter packet (bad version %u" 242*25730d8bSEdward Cree "); counters may be inaccurate\n", 243*25730d8bSEdward Cree version); 244*25730d8bSEdward Cree goto out; 245*25730d8bSEdward Cree } 246*25730d8bSEdward Cree 247*25730d8bSEdward Cree /* Update seen_gen unconditionally, to avoid a missed wakeup if 248*25730d8bSEdward Cree * we race with efx_mae_stop_counters(). 249*25730d8bSEdward Cree */ 250*25730d8bSEdward Cree efx->tc->seen_gen[type] = mark; 251*25730d8bSEdward Cree if (efx->tc->flush_counters && 252*25730d8bSEdward Cree (s32)(efx->tc->flush_gen[type] - mark) <= 0) 253*25730d8bSEdward Cree wake_up(&efx->tc->flush_wq); 254*25730d8bSEdward Cree out: 255*25730d8bSEdward Cree efx_free_rx_buffers(rx_queue, rx_buf, 1); 256*25730d8bSEdward Cree channel->rx_pkt_n_frags = 0; 257*25730d8bSEdward Cree return true; 258*25730d8bSEdward Cree } 259*25730d8bSEdward Cree 260*25730d8bSEdward Cree const struct efx_channel_type efx_tc_channel_type = { 261*25730d8bSEdward Cree .handle_no_channel = efx_tc_handle_no_channel, 262*25730d8bSEdward Cree .pre_probe = efx_tc_probe_channel, 263*25730d8bSEdward Cree .start = efx_tc_start_channel, 264*25730d8bSEdward Cree .stop = efx_tc_stop_channel, 265*25730d8bSEdward Cree .post_remove = efx_tc_remove_channel, 266*25730d8bSEdward Cree .get_name = efx_tc_get_channel_name, 267*25730d8bSEdward Cree .receive_raw = efx_tc_rx, 268*25730d8bSEdward Cree .keep_eventq = true, 269*25730d8bSEdward Cree }; 270