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

Merge branch 'ena-driver-metrics-changes'

David Arinzon says:

====================
ENA driver metrics changes

This patchset contains an introduction of new metrics
available to ENA users.
====================

Link: https://patch.msgid.link/20240909084704.13856-1-darinzon@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+443 -69
+5
Documentation/networking/device_drivers/ethernet/amazon/ena.rst
··· 230 230 231 231 In addition the driver logs the stats to syslog upon device reset. 232 232 233 + On supported instance types, the statistics will also include the 234 + ENA Express data (fields prefixed with `ena_srd`). For a complete 235 + documentation of ENA Express data refer to 236 + https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ena-express.html#ena-express-monitor 237 + 233 238 MTU 234 239 === 235 240
+72
drivers/net/ethernet/amazon/ena/ena_admin_defs.h
··· 7 7 8 8 #define ENA_ADMIN_RSS_KEY_PARTS 10 9 9 10 + #define ENA_ADMIN_CUSTOMER_METRICS_SUPPORT_MASK 0x3F 11 + #define ENA_ADMIN_CUSTOMER_METRICS_MIN_SUPPORT_MASK 0x1F 12 + 13 + /* customer metrics - in correlation with 14 + * ENA_ADMIN_CUSTOMER_METRICS_SUPPORT_MASK 15 + */ 16 + enum ena_admin_customer_metrics_id { 17 + ENA_ADMIN_BW_IN_ALLOWANCE_EXCEEDED = 0, 18 + ENA_ADMIN_BW_OUT_ALLOWANCE_EXCEEDED = 1, 19 + ENA_ADMIN_PPS_ALLOWANCE_EXCEEDED = 2, 20 + ENA_ADMIN_CONNTRACK_ALLOWANCE_EXCEEDED = 3, 21 + ENA_ADMIN_LINKLOCAL_ALLOWANCE_EXCEEDED = 4, 22 + ENA_ADMIN_CONNTRACK_ALLOWANCE_AVAILABLE = 5, 23 + }; 24 + 10 25 enum ena_admin_aq_opcode { 11 26 ENA_ADMIN_CREATE_SQ = 1, 12 27 ENA_ADMIN_DESTROY_SQ = 2, ··· 66 51 /* device capabilities */ 67 52 enum ena_admin_aq_caps_id { 68 53 ENA_ADMIN_ENI_STATS = 0, 54 + /* ENA SRD customer metrics */ 55 + ENA_ADMIN_ENA_SRD_INFO = 1, 56 + ENA_ADMIN_CUSTOMER_METRICS = 2, 69 57 }; 70 58 71 59 enum ena_admin_placement_policy_type { ··· 117 99 ENA_ADMIN_GET_STATS_TYPE_EXTENDED = 1, 118 100 /* extra HW stats for specific network interface */ 119 101 ENA_ADMIN_GET_STATS_TYPE_ENI = 2, 102 + /* extra HW stats for ENA SRD */ 103 + ENA_ADMIN_GET_STATS_TYPE_ENA_SRD = 3, 104 + ENA_ADMIN_GET_STATS_TYPE_CUSTOMER_METRICS = 4, 120 105 }; 121 106 122 107 enum ena_admin_get_stats_scope { 123 108 ENA_ADMIN_SPECIFIC_QUEUE = 0, 124 109 ENA_ADMIN_ETH_TRAFFIC = 1, 110 + }; 111 + 112 + /* ENA SRD configuration for ENI */ 113 + enum ena_admin_ena_srd_flags { 114 + /* Feature enabled */ 115 + ENA_ADMIN_ENA_SRD_ENABLED = BIT(0), 116 + /* UDP support enabled */ 117 + ENA_ADMIN_ENA_SRD_UDP_ENABLED = BIT(1), 118 + /* Bypass Rx UDP ordering */ 119 + ENA_ADMIN_ENA_SRD_UDP_ORDERING_BYPASS_ENABLED = BIT(2), 125 120 }; 126 121 127 122 struct ena_admin_aq_common_desc { ··· 394 363 * stats of other device 395 364 */ 396 365 u16 device_id; 366 + 367 + /* a bitmap representing the requested metric values */ 368 + u64 requested_metrics; 397 369 }; 398 370 399 371 /* Basic Statistics Command. */ ··· 453 419 u64 linklocal_allowance_exceeded; 454 420 }; 455 421 422 + struct ena_admin_ena_srd_stats { 423 + /* Number of packets transmitted over ENA SRD */ 424 + u64 ena_srd_tx_pkts; 425 + 426 + /* Number of packets transmitted or could have been 427 + * transmitted over ENA SRD 428 + */ 429 + u64 ena_srd_eligible_tx_pkts; 430 + 431 + /* Number of packets received over ENA SRD */ 432 + u64 ena_srd_rx_pkts; 433 + 434 + /* Percentage of the ENA SRD resources that is in use */ 435 + u64 ena_srd_resource_utilization; 436 + }; 437 + 438 + /* ENA SRD Statistics Command */ 439 + struct ena_admin_ena_srd_info { 440 + /* ENA SRD configuration bitmap. See ena_admin_ena_srd_flags for 441 + * details 442 + */ 443 + u64 flags; 444 + 445 + struct ena_admin_ena_srd_stats ena_srd_stats; 446 + }; 447 + 448 + /* Customer Metrics Command. */ 449 + struct ena_admin_customer_metrics { 450 + /* A bitmap representing the reported customer metrics according to 451 + * the order they are reported 452 + */ 453 + u64 reported_metrics; 454 + }; 455 + 456 456 struct ena_admin_acq_get_stats_resp { 457 457 struct ena_admin_acq_common_desc acq_common_desc; 458 458 ··· 496 428 struct ena_admin_basic_stats basic_stats; 497 429 498 430 struct ena_admin_eni_stats eni_stats; 431 + 432 + struct ena_admin_ena_srd_info ena_srd_info; 433 + 434 + struct ena_admin_customer_metrics customer_metrics; 499 435 } u; 500 436 }; 501 437
+148 -27
drivers/net/ethernet/amazon/ena/ena_com.c
··· 1881 1881 return ena_com_get_feature(ena_dev, resp, ENA_ADMIN_LINK_CONFIG, 0); 1882 1882 } 1883 1883 1884 + static int ena_get_dev_stats(struct ena_com_dev *ena_dev, 1885 + struct ena_com_stats_ctx *ctx, 1886 + enum ena_admin_get_stats_type type) 1887 + { 1888 + struct ena_admin_acq_get_stats_resp *get_resp = &ctx->get_resp; 1889 + struct ena_admin_aq_get_stats_cmd *get_cmd = &ctx->get_cmd; 1890 + struct ena_com_admin_queue *admin_queue; 1891 + int ret; 1892 + 1893 + admin_queue = &ena_dev->admin_queue; 1894 + 1895 + get_cmd->aq_common_descriptor.opcode = ENA_ADMIN_GET_STATS; 1896 + get_cmd->aq_common_descriptor.flags = 0; 1897 + get_cmd->type = type; 1898 + 1899 + ret = ena_com_execute_admin_command(admin_queue, 1900 + (struct ena_admin_aq_entry *)get_cmd, 1901 + sizeof(*get_cmd), 1902 + (struct ena_admin_acq_entry *)get_resp, 1903 + sizeof(*get_resp)); 1904 + 1905 + if (unlikely(ret)) 1906 + netdev_err(ena_dev->net_device, "Failed to get stats. error: %d\n", ret); 1907 + 1908 + return ret; 1909 + } 1910 + 1911 + static void ena_com_set_supported_customer_metrics(struct ena_com_dev *ena_dev) 1912 + { 1913 + struct ena_customer_metrics *customer_metrics; 1914 + struct ena_com_stats_ctx ctx; 1915 + int ret; 1916 + 1917 + customer_metrics = &ena_dev->customer_metrics; 1918 + if (!ena_com_get_cap(ena_dev, ENA_ADMIN_CUSTOMER_METRICS)) { 1919 + customer_metrics->supported_metrics = ENA_ADMIN_CUSTOMER_METRICS_MIN_SUPPORT_MASK; 1920 + return; 1921 + } 1922 + 1923 + memset(&ctx, 0x0, sizeof(ctx)); 1924 + ctx.get_cmd.requested_metrics = ENA_ADMIN_CUSTOMER_METRICS_SUPPORT_MASK; 1925 + ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_CUSTOMER_METRICS); 1926 + if (likely(ret == 0)) 1927 + customer_metrics->supported_metrics = 1928 + ctx.get_resp.u.customer_metrics.reported_metrics; 1929 + else 1930 + netdev_err(ena_dev->net_device, 1931 + "Failed to query customer metrics support. error: %d\n", ret); 1932 + } 1933 + 1884 1934 int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev, 1885 1935 struct ena_com_dev_get_features_ctx *get_feat_ctx) 1886 1936 { ··· 2009 1959 memset(&get_feat_ctx->llq, 0x0, sizeof(get_feat_ctx->llq)); 2010 1960 else 2011 1961 return rc; 1962 + 1963 + ena_com_set_supported_customer_metrics(ena_dev); 2012 1964 2013 1965 return 0; 2014 1966 } ··· 2156 2104 return 0; 2157 2105 } 2158 2106 2159 - static int ena_get_dev_stats(struct ena_com_dev *ena_dev, 2160 - struct ena_com_stats_ctx *ctx, 2161 - enum ena_admin_get_stats_type type) 2162 - { 2163 - struct ena_admin_aq_get_stats_cmd *get_cmd = &ctx->get_cmd; 2164 - struct ena_admin_acq_get_stats_resp *get_resp = &ctx->get_resp; 2165 - struct ena_com_admin_queue *admin_queue; 2166 - int ret; 2167 - 2168 - admin_queue = &ena_dev->admin_queue; 2169 - 2170 - get_cmd->aq_common_descriptor.opcode = ENA_ADMIN_GET_STATS; 2171 - get_cmd->aq_common_descriptor.flags = 0; 2172 - get_cmd->type = type; 2173 - 2174 - ret = ena_com_execute_admin_command(admin_queue, 2175 - (struct ena_admin_aq_entry *)get_cmd, 2176 - sizeof(*get_cmd), 2177 - (struct ena_admin_acq_entry *)get_resp, 2178 - sizeof(*get_resp)); 2179 - 2180 - if (unlikely(ret)) 2181 - netdev_err(ena_dev->net_device, "Failed to get stats. error: %d\n", ret); 2182 - 2183 - return ret; 2184 - } 2185 - 2186 2107 int ena_com_get_eni_stats(struct ena_com_dev *ena_dev, 2187 2108 struct ena_admin_eni_stats *stats) 2188 2109 { ··· 2177 2152 return ret; 2178 2153 } 2179 2154 2155 + int ena_com_get_ena_srd_info(struct ena_com_dev *ena_dev, 2156 + struct ena_admin_ena_srd_info *info) 2157 + { 2158 + struct ena_com_stats_ctx ctx; 2159 + int ret; 2160 + 2161 + if (!ena_com_get_cap(ena_dev, ENA_ADMIN_ENA_SRD_INFO)) { 2162 + netdev_err(ena_dev->net_device, "Capability %d isn't supported\n", 2163 + ENA_ADMIN_ENA_SRD_INFO); 2164 + return -EOPNOTSUPP; 2165 + } 2166 + 2167 + memset(&ctx, 0x0, sizeof(ctx)); 2168 + ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_ENA_SRD); 2169 + if (likely(ret == 0)) 2170 + memcpy(info, &ctx.get_resp.u.ena_srd_info, 2171 + sizeof(ctx.get_resp.u.ena_srd_info)); 2172 + 2173 + return ret; 2174 + } 2175 + 2180 2176 int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev, 2181 2177 struct ena_admin_basic_stats *stats) 2182 2178 { ··· 2209 2163 if (likely(ret == 0)) 2210 2164 memcpy(stats, &ctx.get_resp.u.basic_stats, 2211 2165 sizeof(ctx.get_resp.u.basic_stats)); 2166 + 2167 + return ret; 2168 + } 2169 + 2170 + int ena_com_get_customer_metrics(struct ena_com_dev *ena_dev, char *buffer, u32 len) 2171 + { 2172 + struct ena_admin_aq_get_stats_cmd *get_cmd; 2173 + struct ena_com_stats_ctx ctx; 2174 + int ret; 2175 + 2176 + if (unlikely(len > ena_dev->customer_metrics.buffer_len)) { 2177 + netdev_err(ena_dev->net_device, 2178 + "Invalid buffer size %u. The given buffer is too big.\n", len); 2179 + return -EINVAL; 2180 + } 2181 + 2182 + if (!ena_com_get_cap(ena_dev, ENA_ADMIN_CUSTOMER_METRICS)) { 2183 + netdev_err(ena_dev->net_device, "Capability %d not supported.\n", 2184 + ENA_ADMIN_CUSTOMER_METRICS); 2185 + return -EOPNOTSUPP; 2186 + } 2187 + 2188 + if (!ena_dev->customer_metrics.supported_metrics) { 2189 + netdev_err(ena_dev->net_device, "No supported customer metrics.\n"); 2190 + return -EOPNOTSUPP; 2191 + } 2192 + 2193 + get_cmd = &ctx.get_cmd; 2194 + memset(&ctx, 0x0, sizeof(ctx)); 2195 + ret = ena_com_mem_addr_set(ena_dev, 2196 + &get_cmd->u.control_buffer.address, 2197 + ena_dev->customer_metrics.buffer_dma_addr); 2198 + if (unlikely(ret)) { 2199 + netdev_err(ena_dev->net_device, "Memory address set failed.\n"); 2200 + return ret; 2201 + } 2202 + 2203 + get_cmd->u.control_buffer.length = ena_dev->customer_metrics.buffer_len; 2204 + get_cmd->requested_metrics = ena_dev->customer_metrics.supported_metrics; 2205 + ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_CUSTOMER_METRICS); 2206 + if (likely(ret == 0)) 2207 + memcpy(buffer, ena_dev->customer_metrics.buffer_virt_addr, len); 2208 + else 2209 + netdev_err(ena_dev->net_device, "Failed to get customer metrics. error: %d\n", ret); 2212 2210 2213 2211 return ret; 2214 2212 } ··· 2796 2706 return 0; 2797 2707 } 2798 2708 2709 + int ena_com_allocate_customer_metrics_buffer(struct ena_com_dev *ena_dev) 2710 + { 2711 + struct ena_customer_metrics *customer_metrics = &ena_dev->customer_metrics; 2712 + 2713 + customer_metrics->buffer_len = ENA_CUSTOMER_METRICS_BUFFER_SIZE; 2714 + customer_metrics->buffer_virt_addr = NULL; 2715 + 2716 + customer_metrics->buffer_virt_addr = 2717 + dma_alloc_coherent(ena_dev->dmadev, customer_metrics->buffer_len, 2718 + &customer_metrics->buffer_dma_addr, GFP_KERNEL); 2719 + if (!customer_metrics->buffer_virt_addr) { 2720 + customer_metrics->buffer_len = 0; 2721 + return -ENOMEM; 2722 + } 2723 + 2724 + return 0; 2725 + } 2726 + 2799 2727 void ena_com_delete_host_info(struct ena_com_dev *ena_dev) 2800 2728 { 2801 2729 struct ena_host_attribute *host_attr = &ena_dev->host_attr; ··· 2833 2725 dma_free_coherent(ena_dev->dmadev, host_attr->debug_area_size, 2834 2726 host_attr->debug_area_virt_addr, host_attr->debug_area_dma_addr); 2835 2727 host_attr->debug_area_virt_addr = NULL; 2728 + } 2729 + } 2730 + 2731 + void ena_com_delete_customer_metrics_buffer(struct ena_com_dev *ena_dev) 2732 + { 2733 + struct ena_customer_metrics *customer_metrics = &ena_dev->customer_metrics; 2734 + 2735 + if (customer_metrics->buffer_virt_addr) { 2736 + dma_free_coherent(ena_dev->dmadev, customer_metrics->buffer_len, 2737 + customer_metrics->buffer_virt_addr, 2738 + customer_metrics->buffer_dma_addr); 2739 + customer_metrics->buffer_virt_addr = NULL; 2740 + customer_metrics->buffer_len = 0; 2836 2741 } 2837 2742 } 2838 2743
+68
drivers/net/ethernet/amazon/ena/ena_com.h
··· 42 42 #define ADMIN_CQ_SIZE(depth) ((depth) * sizeof(struct ena_admin_acq_entry)) 43 43 #define ADMIN_AENQ_SIZE(depth) ((depth) * sizeof(struct ena_admin_aenq_entry)) 44 44 45 + #define ENA_CUSTOMER_METRICS_BUFFER_SIZE 512 46 + 45 47 /*****************************************************************************/ 46 48 /*****************************************************************************/ 47 49 /* ENA adaptive interrupt moderation settings */ ··· 280 278 281 279 }; 282 280 281 + struct ena_customer_metrics { 282 + /* in correlation with ENA_ADMIN_CUSTOMER_METRICS_SUPPORT_MASK 283 + * and ena_admin_customer_metrics_id 284 + */ 285 + u64 supported_metrics; 286 + dma_addr_t buffer_dma_addr; 287 + void *buffer_virt_addr; 288 + u32 buffer_len; 289 + }; 290 + 283 291 struct ena_host_attribute { 284 292 /* Debug area */ 285 293 u8 *debug_area_virt_addr; ··· 339 327 struct ena_intr_moder_entry *intr_moder_tbl; 340 328 341 329 struct ena_com_llq_info llq_info; 330 + 331 + struct ena_customer_metrics customer_metrics; 342 332 }; 343 333 344 334 struct ena_com_dev_get_features_ctx { ··· 609 595 int ena_com_get_eni_stats(struct ena_com_dev *ena_dev, 610 596 struct ena_admin_eni_stats *stats); 611 597 598 + /* ena_com_get_ena_srd_info - Get ENA SRD network interface statistics 599 + * @ena_dev: ENA communication layer struct 600 + * @info: ena srd stats and flags 601 + * 602 + * @return: 0 on Success and negative value otherwise. 603 + */ 604 + int ena_com_get_ena_srd_info(struct ena_com_dev *ena_dev, 605 + struct ena_admin_ena_srd_info *info); 606 + 607 + /* ena_com_get_customer_metrics - Get customer metrics for network interface 608 + * @ena_dev: ENA communication layer struct 609 + * @buffer: buffer for returned customer metrics 610 + * @len: size of the buffer 611 + * 612 + * @return: 0 on Success and negative value otherwise. 613 + */ 614 + int ena_com_get_customer_metrics(struct ena_com_dev *ena_dev, char *buffer, u32 len); 615 + 612 616 /* ena_com_set_dev_mtu - Configure the device mtu. 613 617 * @ena_dev: ENA communication layer struct 614 618 * @mtu: mtu value ··· 837 805 int ena_com_allocate_debug_area(struct ena_com_dev *ena_dev, 838 806 u32 debug_area_size); 839 807 808 + /* ena_com_allocate_customer_metrics_buffer - Allocate customer metrics resources. 809 + * @ena_dev: ENA communication layer struct 810 + * 811 + * @return: 0 on Success and negative value otherwise. 812 + */ 813 + int ena_com_allocate_customer_metrics_buffer(struct ena_com_dev *ena_dev); 814 + 840 815 /* ena_com_delete_debug_area - Free the debug area resources. 841 816 * @ena_dev: ENA communication layer struct 842 817 * ··· 857 818 * Free the allocated host info. 858 819 */ 859 820 void ena_com_delete_host_info(struct ena_com_dev *ena_dev); 821 + 822 + /* ena_com_delete_customer_metrics_buffer - Free the customer metrics resources. 823 + * @ena_dev: ENA communication layer struct 824 + * 825 + * Free the allocated customer metrics area. 826 + */ 827 + void ena_com_delete_customer_metrics_buffer(struct ena_com_dev *ena_dev); 860 828 861 829 /* ena_com_set_host_attributes - Update the device with the host 862 830 * attributes (debug area and host info) base address. ··· 1019 973 enum ena_admin_aq_caps_id cap_id) 1020 974 { 1021 975 return !!(ena_dev->capabilities & BIT(cap_id)); 976 + } 977 + 978 + /* ena_com_get_customer_metric_support - query whether device supports a given customer metric. 979 + * @ena_dev: ENA communication layer struct 980 + * @metric_id: enum value representing the customer metric 981 + * 982 + * @return - true if customer metric is supported or false otherwise 983 + */ 984 + static inline bool ena_com_get_customer_metric_support(struct ena_com_dev *ena_dev, 985 + enum ena_admin_customer_metrics_id metric_id) 986 + { 987 + return !!(ena_dev->customer_metrics.supported_metrics & BIT(metric_id)); 988 + } 989 + 990 + /* ena_com_get_customer_metric_count - return the number of supported customer metrics. 991 + * @ena_dev: ENA communication layer struct 992 + * 993 + * @return - the number of supported customer metrics 994 + */ 995 + static inline int ena_com_get_customer_metric_count(struct ena_com_dev *ena_dev) 996 + { 997 + return hweight64(ena_dev->customer_metrics.supported_metrics); 1022 998 } 1023 999 1024 1000 /* ena_com_update_intr_reg - Prepare interrupt register
+137 -26
drivers/net/ethernet/amazon/ena/ena_ethtool.c
··· 14 14 int stat_offset; 15 15 }; 16 16 17 + struct ena_hw_metrics { 18 + char name[ETH_GSTRING_LEN]; 19 + }; 20 + 17 21 #define ENA_STAT_ENA_COM_ENTRY(stat) { \ 18 22 .name = #stat, \ 19 23 .stat_offset = offsetof(struct ena_com_stats_admin, stat) / sizeof(u64) \ ··· 45 41 #define ENA_STAT_ENI_ENTRY(stat) \ 46 42 ENA_STAT_HW_ENTRY(stat, eni_stats) 47 43 44 + #define ENA_STAT_ENA_SRD_ENTRY(stat) \ 45 + ENA_STAT_HW_ENTRY(stat, ena_srd_stats) 46 + 47 + #define ENA_STAT_ENA_SRD_MODE_ENTRY(stat) { \ 48 + .name = #stat, \ 49 + .stat_offset = offsetof(struct ena_admin_ena_srd_info, flags) / sizeof(u64) \ 50 + } 51 + 52 + #define ENA_METRIC_ENI_ENTRY(stat) { \ 53 + .name = #stat \ 54 + } 55 + 48 56 static const struct ena_stats ena_stats_global_strings[] = { 49 57 ENA_STAT_GLOBAL_ENTRY(tx_timeout), 50 58 ENA_STAT_GLOBAL_ENTRY(suspend), ··· 68 52 ENA_STAT_GLOBAL_ENTRY(reset_fail), 69 53 }; 70 54 55 + /* A partial list of hw stats. Used when admin command 56 + * with type ENA_ADMIN_GET_STATS_TYPE_CUSTOMER_METRICS is not supported 57 + */ 71 58 static const struct ena_stats ena_stats_eni_strings[] = { 72 59 ENA_STAT_ENI_ENTRY(bw_in_allowance_exceeded), 73 60 ENA_STAT_ENI_ENTRY(bw_out_allowance_exceeded), 74 61 ENA_STAT_ENI_ENTRY(pps_allowance_exceeded), 75 62 ENA_STAT_ENI_ENTRY(conntrack_allowance_exceeded), 76 63 ENA_STAT_ENI_ENTRY(linklocal_allowance_exceeded), 64 + }; 65 + 66 + static const struct ena_hw_metrics ena_hw_stats_strings[] = { 67 + ENA_METRIC_ENI_ENTRY(bw_in_allowance_exceeded), 68 + ENA_METRIC_ENI_ENTRY(bw_out_allowance_exceeded), 69 + ENA_METRIC_ENI_ENTRY(pps_allowance_exceeded), 70 + ENA_METRIC_ENI_ENTRY(conntrack_allowance_exceeded), 71 + ENA_METRIC_ENI_ENTRY(linklocal_allowance_exceeded), 72 + ENA_METRIC_ENI_ENTRY(conntrack_allowance_available), 73 + }; 74 + 75 + static const struct ena_stats ena_srd_info_strings[] = { 76 + ENA_STAT_ENA_SRD_MODE_ENTRY(ena_srd_mode), 77 + ENA_STAT_ENA_SRD_ENTRY(ena_srd_tx_pkts), 78 + ENA_STAT_ENA_SRD_ENTRY(ena_srd_eligible_tx_pkts), 79 + ENA_STAT_ENA_SRD_ENTRY(ena_srd_rx_pkts), 80 + ENA_STAT_ENA_SRD_ENTRY(ena_srd_resource_utilization) 77 81 }; 78 82 79 83 static const struct ena_stats ena_stats_tx_strings[] = { ··· 148 112 #define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings) 149 113 #define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings) 150 114 #define ENA_STATS_ARRAY_ENA_COM ARRAY_SIZE(ena_stats_ena_com_strings) 151 - #define ENA_STATS_ARRAY_ENI(adapter) ARRAY_SIZE(ena_stats_eni_strings) 115 + #define ENA_STATS_ARRAY_ENI ARRAY_SIZE(ena_stats_eni_strings) 116 + #define ENA_STATS_ARRAY_ENA_SRD ARRAY_SIZE(ena_srd_info_strings) 117 + #define ENA_METRICS_ARRAY_ENI ARRAY_SIZE(ena_hw_stats_strings) 152 118 153 119 static void ena_safe_update_stat(u64 *src, u64 *dst, 154 120 struct u64_stats_sync *syncp) ··· 161 123 start = u64_stats_fetch_begin(syncp); 162 124 *(dst) = *src; 163 125 } while (u64_stats_fetch_retry(syncp, start)); 126 + } 127 + 128 + static void ena_metrics_stats(struct ena_adapter *adapter, u64 **data) 129 + { 130 + struct ena_com_dev *dev = adapter->ena_dev; 131 + const struct ena_stats *ena_stats; 132 + u64 *ptr; 133 + int i; 134 + 135 + if (ena_com_get_cap(dev, ENA_ADMIN_CUSTOMER_METRICS)) { 136 + u32 supported_metrics_count; 137 + int len; 138 + 139 + supported_metrics_count = ena_com_get_customer_metric_count(dev); 140 + len = supported_metrics_count * sizeof(u64); 141 + 142 + /* Fill the data buffer, and advance its pointer */ 143 + ena_com_get_customer_metrics(dev, (char *)(*data), len); 144 + (*data) += supported_metrics_count; 145 + 146 + } else if (ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS)) { 147 + ena_com_get_eni_stats(dev, &adapter->eni_stats); 148 + /* Updating regardless of rc - once we told ethtool how many stats we have 149 + * it will print that much stats. We can't leave holes in the stats 150 + */ 151 + for (i = 0; i < ENA_STATS_ARRAY_ENI; i++) { 152 + ena_stats = &ena_stats_eni_strings[i]; 153 + 154 + ptr = (u64 *)&adapter->eni_stats + 155 + ena_stats->stat_offset; 156 + 157 + ena_safe_update_stat(ptr, (*data)++, &adapter->syncp); 158 + } 159 + } 160 + 161 + if (ena_com_get_cap(dev, ENA_ADMIN_ENA_SRD_INFO)) { 162 + ena_com_get_ena_srd_info(dev, &adapter->ena_srd_info); 163 + /* Get ENA SRD mode */ 164 + ptr = (u64 *)&adapter->ena_srd_info; 165 + ena_safe_update_stat(ptr, (*data)++, &adapter->syncp); 166 + for (i = 1; i < ENA_STATS_ARRAY_ENA_SRD; i++) { 167 + ena_stats = &ena_srd_info_strings[i]; 168 + /* Wrapped within an outer struct - need to accommodate an 169 + * additional offset of the ENA SRD mode that was already processed 170 + */ 171 + ptr = (u64 *)&adapter->ena_srd_info + 172 + ena_stats->stat_offset + 1; 173 + 174 + ena_safe_update_stat(ptr, (*data)++, &adapter->syncp); 175 + } 176 + } 164 177 } 165 178 166 179 static void ena_queue_stats(struct ena_adapter *adapter, u64 **data) ··· 268 179 269 180 static void ena_get_stats(struct ena_adapter *adapter, 270 181 u64 *data, 271 - bool eni_stats_needed) 182 + bool hw_stats_needed) 272 183 { 273 184 const struct ena_stats *ena_stats; 274 185 u64 *ptr; ··· 282 193 ena_safe_update_stat(ptr, data++, &adapter->syncp); 283 194 } 284 195 285 - if (eni_stats_needed) { 286 - ena_update_hw_stats(adapter); 287 - for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) { 288 - ena_stats = &ena_stats_eni_strings[i]; 289 - 290 - ptr = (u64 *)&adapter->eni_stats + 291 - ena_stats->stat_offset; 292 - 293 - ena_safe_update_stat(ptr, data++, &adapter->syncp); 294 - } 295 - } 196 + if (hw_stats_needed) 197 + ena_metrics_stats(adapter, &data); 296 198 297 199 ena_queue_stats(adapter, &data); 298 200 ena_dev_admin_queue_stats(adapter, &data); ··· 294 214 u64 *data) 295 215 { 296 216 struct ena_adapter *adapter = netdev_priv(netdev); 297 - struct ena_com_dev *dev = adapter->ena_dev; 298 217 299 - ena_get_stats(adapter, data, ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS)); 218 + ena_get_stats(adapter, data, true); 300 219 } 301 220 302 221 static int ena_get_sw_stats_count(struct ena_adapter *adapter) ··· 307 228 308 229 static int ena_get_hw_stats_count(struct ena_adapter *adapter) 309 230 { 310 - bool supported = ena_com_get_cap(adapter->ena_dev, ENA_ADMIN_ENI_STATS); 231 + struct ena_com_dev *dev = adapter->ena_dev; 232 + int count; 311 233 312 - return ENA_STATS_ARRAY_ENI(adapter) * supported; 234 + count = ENA_STATS_ARRAY_ENA_SRD * ena_com_get_cap(dev, ENA_ADMIN_ENA_SRD_INFO); 235 + 236 + if (ena_com_get_cap(dev, ENA_ADMIN_CUSTOMER_METRICS)) 237 + count += ena_com_get_customer_metric_count(dev); 238 + else if (ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS)) 239 + count += ENA_STATS_ARRAY_ENI; 240 + 241 + return count; 313 242 } 314 243 315 244 int ena_get_sset_count(struct net_device *netdev, int sset) ··· 331 244 } 332 245 333 246 return -EOPNOTSUPP; 247 + } 248 + 249 + static void ena_metrics_stats_strings(struct ena_adapter *adapter, u8 **data) 250 + { 251 + struct ena_com_dev *dev = adapter->ena_dev; 252 + const struct ena_hw_metrics *ena_metrics; 253 + const struct ena_stats *ena_stats; 254 + int i; 255 + 256 + if (ena_com_get_cap(dev, ENA_ADMIN_CUSTOMER_METRICS)) { 257 + for (i = 0; i < ENA_METRICS_ARRAY_ENI; i++) { 258 + if (ena_com_get_customer_metric_support(dev, i)) { 259 + ena_metrics = &ena_hw_stats_strings[i]; 260 + ethtool_puts(data, ena_metrics->name); 261 + } 262 + } 263 + } else if (ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS)) { 264 + for (i = 0; i < ENA_STATS_ARRAY_ENI; i++) { 265 + ena_stats = &ena_stats_eni_strings[i]; 266 + ethtool_puts(data, ena_stats->name); 267 + } 268 + } 269 + 270 + if (ena_com_get_cap(dev, ENA_ADMIN_ENA_SRD_INFO)) { 271 + for (i = 0; i < ENA_STATS_ARRAY_ENA_SRD; i++) { 272 + ena_stats = &ena_srd_info_strings[i]; 273 + ethtool_puts(data, ena_stats->name); 274 + } 275 + } 334 276 } 335 277 336 278 static void ena_queue_strings(struct ena_adapter *adapter, u8 **data) ··· 407 291 408 292 static void ena_get_strings(struct ena_adapter *adapter, 409 293 u8 *data, 410 - bool eni_stats_needed) 294 + bool hw_stats_needed) 411 295 { 412 296 const struct ena_stats *ena_stats; 413 297 int i; ··· 417 301 ethtool_puts(&data, ena_stats->name); 418 302 } 419 303 420 - if (eni_stats_needed) { 421 - for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) { 422 - ena_stats = &ena_stats_eni_strings[i]; 423 - ethtool_puts(&data, ena_stats->name); 424 - } 425 - } 304 + if (hw_stats_needed) 305 + ena_metrics_stats_strings(adapter, &data); 426 306 427 307 ena_queue_strings(adapter, &data); 428 308 ena_com_dev_strings(&data); ··· 429 317 u8 *data) 430 318 { 431 319 struct ena_adapter *adapter = netdev_priv(netdev); 432 - struct ena_com_dev *dev = adapter->ena_dev; 433 320 434 321 switch (sset) { 435 322 case ETH_SS_STATS: 436 - ena_get_strings(adapter, data, ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS)); 323 + ena_get_strings(adapter, data, true); 437 324 break; 438 325 } 439 326 }
+12 -15
drivers/net/ethernet/amazon/ena/ena_netdev.c
··· 2798 2798 ena_com_delete_debug_area(adapter->ena_dev); 2799 2799 } 2800 2800 2801 - int ena_update_hw_stats(struct ena_adapter *adapter) 2802 - { 2803 - int rc; 2804 - 2805 - rc = ena_com_get_eni_stats(adapter->ena_dev, &adapter->eni_stats); 2806 - if (rc) { 2807 - netdev_err(adapter->netdev, "Failed to get ENI stats\n"); 2808 - return rc; 2809 - } 2810 - 2811 - return 0; 2812 - } 2813 - 2814 2801 static void ena_get_stats64(struct net_device *netdev, 2815 2802 struct rtnl_link_stats64 *stats) 2816 2803 { ··· 3931 3944 3932 3945 pci_set_drvdata(pdev, adapter); 3933 3946 3947 + rc = ena_com_allocate_customer_metrics_buffer(ena_dev); 3948 + if (rc) { 3949 + netdev_err(netdev, "ena_com_allocate_customer_metrics_buffer failed\n"); 3950 + goto err_netdev_destroy; 3951 + } 3952 + 3934 3953 rc = ena_map_llq_mem_bar(pdev, ena_dev, bars); 3935 3954 if (rc) { 3936 3955 dev_err(&pdev->dev, "ENA LLQ bar mapping failed\n"); 3937 - goto err_netdev_destroy; 3956 + goto err_metrics_destroy; 3938 3957 } 3939 3958 3940 3959 rc = ena_device_init(adapter, pdev, &get_feat_ctx, &wd_state); ··· 3948 3955 dev_err(&pdev->dev, "ENA device init failed\n"); 3949 3956 if (rc == -ETIME) 3950 3957 rc = -EPROBE_DEFER; 3951 - goto err_netdev_destroy; 3958 + goto err_metrics_destroy; 3952 3959 } 3953 3960 3954 3961 /* Initial TX and RX interrupt delay. Assumes 1 usec granularity. ··· 4069 4076 err_device_destroy: 4070 4077 ena_com_delete_host_info(ena_dev); 4071 4078 ena_com_admin_destroy(ena_dev); 4079 + err_metrics_destroy: 4080 + ena_com_delete_customer_metrics_buffer(ena_dev); 4072 4081 err_netdev_destroy: 4073 4082 free_netdev(netdev); 4074 4083 err_free_region: ··· 4133 4138 ena_com_delete_debug_area(ena_dev); 4134 4139 4135 4140 ena_com_delete_host_info(ena_dev); 4141 + 4142 + ena_com_delete_customer_metrics_buffer(ena_dev); 4136 4143 4137 4144 ena_release_bars(ena_dev, pdev); 4138 4145
+1 -1
drivers/net/ethernet/amazon/ena/ena_netdev.h
··· 373 373 struct u64_stats_sync syncp; 374 374 struct ena_stats_dev dev_stats; 375 375 struct ena_admin_eni_stats eni_stats; 376 + struct ena_admin_ena_srd_info ena_srd_info; 376 377 377 378 /* last queue index that was checked for uncompleted tx packets */ 378 379 u32 last_monitored_tx_qid; ··· 391 390 392 391 void ena_dump_stats_to_buf(struct ena_adapter *adapter, u8 *buf); 393 392 394 - int ena_update_hw_stats(struct ena_adapter *adapter); 395 393 396 394 int ena_update_queue_params(struct ena_adapter *adapter, 397 395 u32 new_tx_size,