.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB |
---|
1 | 2 | /* |
---|
2 | | - * Copyright 2015 Amazon.com, Inc. or its affiliates. |
---|
3 | | - * |
---|
4 | | - * This software is available to you under a choice of one of two |
---|
5 | | - * licenses. You may choose to be licensed under the terms of the GNU |
---|
6 | | - * General Public License (GPL) Version 2, available from the file |
---|
7 | | - * COPYING in the main directory of this source tree, or the |
---|
8 | | - * BSD license below: |
---|
9 | | - * |
---|
10 | | - * Redistribution and use in source and binary forms, with or |
---|
11 | | - * without modification, are permitted provided that the following |
---|
12 | | - * conditions are met: |
---|
13 | | - * |
---|
14 | | - * - Redistributions of source code must retain the above |
---|
15 | | - * copyright notice, this list of conditions and the following |
---|
16 | | - * disclaimer. |
---|
17 | | - * |
---|
18 | | - * - Redistributions in binary form must reproduce the above |
---|
19 | | - * copyright notice, this list of conditions and the following |
---|
20 | | - * disclaimer in the documentation and/or other materials |
---|
21 | | - * provided with the distribution. |
---|
22 | | - * |
---|
23 | | - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
---|
24 | | - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
---|
25 | | - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
---|
26 | | - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
---|
27 | | - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
---|
28 | | - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
---|
29 | | - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
---|
30 | | - * SOFTWARE. |
---|
| 3 | + * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved. |
---|
31 | 4 | */ |
---|
32 | 5 | |
---|
33 | 6 | #include <linux/pci.h> |
---|
.. | .. |
---|
41 | 14 | |
---|
42 | 15 | #define ENA_STAT_ENA_COM_ENTRY(stat) { \ |
---|
43 | 16 | .name = #stat, \ |
---|
44 | | - .stat_offset = offsetof(struct ena_com_stats_admin, stat) \ |
---|
| 17 | + .stat_offset = offsetof(struct ena_com_stats_admin, stat) / sizeof(u64) \ |
---|
45 | 18 | } |
---|
46 | 19 | |
---|
47 | 20 | #define ENA_STAT_ENTRY(stat, stat_type) { \ |
---|
48 | 21 | .name = #stat, \ |
---|
49 | | - .stat_offset = offsetof(struct ena_stats_##stat_type, stat) \ |
---|
| 22 | + .stat_offset = offsetof(struct ena_stats_##stat_type, stat) / sizeof(u64) \ |
---|
| 23 | +} |
---|
| 24 | + |
---|
| 25 | +#define ENA_STAT_HW_ENTRY(stat, stat_type) { \ |
---|
| 26 | + .name = #stat, \ |
---|
| 27 | + .stat_offset = offsetof(struct ena_admin_##stat_type, stat) / sizeof(u64) \ |
---|
50 | 28 | } |
---|
51 | 29 | |
---|
52 | 30 | #define ENA_STAT_RX_ENTRY(stat) \ |
---|
.. | .. |
---|
58 | 36 | #define ENA_STAT_GLOBAL_ENTRY(stat) \ |
---|
59 | 37 | ENA_STAT_ENTRY(stat, dev) |
---|
60 | 38 | |
---|
| 39 | +#define ENA_STAT_ENI_ENTRY(stat) \ |
---|
| 40 | + ENA_STAT_HW_ENTRY(stat, eni_stats) |
---|
| 41 | + |
---|
61 | 42 | static const struct ena_stats ena_stats_global_strings[] = { |
---|
62 | 43 | ENA_STAT_GLOBAL_ENTRY(tx_timeout), |
---|
63 | 44 | ENA_STAT_GLOBAL_ENTRY(suspend), |
---|
.. | .. |
---|
66 | 47 | ENA_STAT_GLOBAL_ENTRY(interface_up), |
---|
67 | 48 | ENA_STAT_GLOBAL_ENTRY(interface_down), |
---|
68 | 49 | ENA_STAT_GLOBAL_ENTRY(admin_q_pause), |
---|
| 50 | +}; |
---|
| 51 | + |
---|
| 52 | +static const struct ena_stats ena_stats_eni_strings[] = { |
---|
| 53 | + ENA_STAT_ENI_ENTRY(bw_in_allowance_exceeded), |
---|
| 54 | + ENA_STAT_ENI_ENTRY(bw_out_allowance_exceeded), |
---|
| 55 | + ENA_STAT_ENI_ENTRY(pps_allowance_exceeded), |
---|
| 56 | + ENA_STAT_ENI_ENTRY(conntrack_allowance_exceeded), |
---|
| 57 | + ENA_STAT_ENI_ENTRY(linklocal_allowance_exceeded), |
---|
69 | 58 | }; |
---|
70 | 59 | |
---|
71 | 60 | static const struct ena_stats ena_stats_tx_strings[] = { |
---|
.. | .. |
---|
81 | 70 | ENA_STAT_TX_ENTRY(doorbells), |
---|
82 | 71 | ENA_STAT_TX_ENTRY(prepare_ctx_err), |
---|
83 | 72 | ENA_STAT_TX_ENTRY(bad_req_id), |
---|
| 73 | + ENA_STAT_TX_ENTRY(llq_buffer_copy), |
---|
84 | 74 | ENA_STAT_TX_ENTRY(missed_tx), |
---|
| 75 | + ENA_STAT_TX_ENTRY(unmask_interrupt), |
---|
85 | 76 | }; |
---|
86 | 77 | |
---|
87 | 78 | static const struct ena_stats ena_stats_rx_strings[] = { |
---|
88 | 79 | ENA_STAT_RX_ENTRY(cnt), |
---|
89 | 80 | ENA_STAT_RX_ENTRY(bytes), |
---|
| 81 | + ENA_STAT_RX_ENTRY(rx_copybreak_pkt), |
---|
| 82 | + ENA_STAT_RX_ENTRY(csum_good), |
---|
90 | 83 | ENA_STAT_RX_ENTRY(refil_partial), |
---|
91 | 84 | ENA_STAT_RX_ENTRY(bad_csum), |
---|
92 | 85 | ENA_STAT_RX_ENTRY(page_alloc_fail), |
---|
93 | 86 | ENA_STAT_RX_ENTRY(skb_alloc_fail), |
---|
94 | 87 | ENA_STAT_RX_ENTRY(dma_mapping_err), |
---|
95 | 88 | ENA_STAT_RX_ENTRY(bad_desc_num), |
---|
96 | | - ENA_STAT_RX_ENTRY(rx_copybreak_pkt), |
---|
97 | 89 | ENA_STAT_RX_ENTRY(bad_req_id), |
---|
98 | 90 | ENA_STAT_RX_ENTRY(empty_rx_ring), |
---|
| 91 | + ENA_STAT_RX_ENTRY(csum_unchecked), |
---|
| 92 | + ENA_STAT_RX_ENTRY(xdp_aborted), |
---|
| 93 | + ENA_STAT_RX_ENTRY(xdp_drop), |
---|
| 94 | + ENA_STAT_RX_ENTRY(xdp_pass), |
---|
| 95 | + ENA_STAT_RX_ENTRY(xdp_tx), |
---|
| 96 | + ENA_STAT_RX_ENTRY(xdp_invalid), |
---|
99 | 97 | }; |
---|
100 | 98 | |
---|
101 | 99 | static const struct ena_stats ena_stats_ena_com_strings[] = { |
---|
.. | .. |
---|
106 | 104 | ENA_STAT_ENA_COM_ENTRY(no_completion), |
---|
107 | 105 | }; |
---|
108 | 106 | |
---|
109 | | -#define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings) |
---|
110 | | -#define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings) |
---|
111 | | -#define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings) |
---|
112 | | -#define ENA_STATS_ARRAY_ENA_COM ARRAY_SIZE(ena_stats_ena_com_strings) |
---|
| 107 | +#define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings) |
---|
| 108 | +#define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings) |
---|
| 109 | +#define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings) |
---|
| 110 | +#define ENA_STATS_ARRAY_ENA_COM ARRAY_SIZE(ena_stats_ena_com_strings) |
---|
| 111 | +#define ENA_STATS_ARRAY_ENI(adapter) \ |
---|
| 112 | + (ARRAY_SIZE(ena_stats_eni_strings) * (adapter)->eni_stats_supported) |
---|
113 | 113 | |
---|
114 | 114 | static void ena_safe_update_stat(u64 *src, u64 *dst, |
---|
115 | 115 | struct u64_stats_sync *syncp) |
---|
.. | .. |
---|
130 | 130 | u64 *ptr; |
---|
131 | 131 | int i, j; |
---|
132 | 132 | |
---|
133 | | - for (i = 0; i < adapter->num_queues; i++) { |
---|
| 133 | + for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) { |
---|
134 | 134 | /* Tx stats */ |
---|
135 | 135 | ring = &adapter->tx_ring[i]; |
---|
136 | 136 | |
---|
137 | 137 | for (j = 0; j < ENA_STATS_ARRAY_TX; j++) { |
---|
138 | 138 | ena_stats = &ena_stats_tx_strings[j]; |
---|
139 | 139 | |
---|
140 | | - ptr = (u64 *)((uintptr_t)&ring->tx_stats + |
---|
141 | | - (uintptr_t)ena_stats->stat_offset); |
---|
| 140 | + ptr = (u64 *)&ring->tx_stats + ena_stats->stat_offset; |
---|
142 | 141 | |
---|
143 | 142 | ena_safe_update_stat(ptr, (*data)++, &ring->syncp); |
---|
144 | 143 | } |
---|
| 144 | + /* XDP TX queues don't have a RX queue counterpart */ |
---|
| 145 | + if (!ENA_IS_XDP_INDEX(adapter, i)) { |
---|
| 146 | + /* Rx stats */ |
---|
| 147 | + ring = &adapter->rx_ring[i]; |
---|
145 | 148 | |
---|
146 | | - /* Rx stats */ |
---|
147 | | - ring = &adapter->rx_ring[i]; |
---|
| 149 | + for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { |
---|
| 150 | + ena_stats = &ena_stats_rx_strings[j]; |
---|
148 | 151 | |
---|
149 | | - for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { |
---|
150 | | - ena_stats = &ena_stats_rx_strings[j]; |
---|
| 152 | + ptr = (u64 *)&ring->rx_stats + |
---|
| 153 | + ena_stats->stat_offset; |
---|
151 | 154 | |
---|
152 | | - ptr = (u64 *)((uintptr_t)&ring->rx_stats + |
---|
153 | | - (uintptr_t)ena_stats->stat_offset); |
---|
154 | | - |
---|
155 | | - ena_safe_update_stat(ptr, (*data)++, &ring->syncp); |
---|
| 155 | + ena_safe_update_stat(ptr, (*data)++, &ring->syncp); |
---|
| 156 | + } |
---|
156 | 157 | } |
---|
157 | 158 | } |
---|
158 | 159 | } |
---|
.. | .. |
---|
160 | 161 | static void ena_dev_admin_queue_stats(struct ena_adapter *adapter, u64 **data) |
---|
161 | 162 | { |
---|
162 | 163 | const struct ena_stats *ena_stats; |
---|
163 | | - u32 *ptr; |
---|
| 164 | + u64 *ptr; |
---|
164 | 165 | int i; |
---|
165 | 166 | |
---|
166 | 167 | for (i = 0; i < ENA_STATS_ARRAY_ENA_COM; i++) { |
---|
167 | 168 | ena_stats = &ena_stats_ena_com_strings[i]; |
---|
168 | 169 | |
---|
169 | | - ptr = (u32 *)((uintptr_t)&adapter->ena_dev->admin_queue.stats + |
---|
170 | | - (uintptr_t)ena_stats->stat_offset); |
---|
| 170 | + ptr = (u64 *)&adapter->ena_dev->admin_queue.stats + |
---|
| 171 | + ena_stats->stat_offset; |
---|
171 | 172 | |
---|
172 | 173 | *(*data)++ = *ptr; |
---|
173 | 174 | } |
---|
174 | 175 | } |
---|
175 | 176 | |
---|
176 | | -static void ena_get_ethtool_stats(struct net_device *netdev, |
---|
177 | | - struct ethtool_stats *stats, |
---|
178 | | - u64 *data) |
---|
| 177 | +static void ena_get_stats(struct ena_adapter *adapter, |
---|
| 178 | + u64 *data, |
---|
| 179 | + bool eni_stats_needed) |
---|
179 | 180 | { |
---|
180 | | - struct ena_adapter *adapter = netdev_priv(netdev); |
---|
181 | 181 | const struct ena_stats *ena_stats; |
---|
182 | 182 | u64 *ptr; |
---|
183 | 183 | int i; |
---|
.. | .. |
---|
185 | 185 | for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) { |
---|
186 | 186 | ena_stats = &ena_stats_global_strings[i]; |
---|
187 | 187 | |
---|
188 | | - ptr = (u64 *)((uintptr_t)&adapter->dev_stats + |
---|
189 | | - (uintptr_t)ena_stats->stat_offset); |
---|
| 188 | + ptr = (u64 *)&adapter->dev_stats + ena_stats->stat_offset; |
---|
190 | 189 | |
---|
191 | 190 | ena_safe_update_stat(ptr, data++, &adapter->syncp); |
---|
192 | 191 | } |
---|
193 | 192 | |
---|
| 193 | + if (eni_stats_needed) { |
---|
| 194 | + ena_update_hw_stats(adapter); |
---|
| 195 | + for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) { |
---|
| 196 | + ena_stats = &ena_stats_eni_strings[i]; |
---|
| 197 | + |
---|
| 198 | + ptr = (u64 *)&adapter->eni_stats + |
---|
| 199 | + ena_stats->stat_offset; |
---|
| 200 | + |
---|
| 201 | + ena_safe_update_stat(ptr, data++, &adapter->syncp); |
---|
| 202 | + } |
---|
| 203 | + } |
---|
| 204 | + |
---|
194 | 205 | ena_queue_stats(adapter, &data); |
---|
195 | 206 | ena_dev_admin_queue_stats(adapter, &data); |
---|
| 207 | +} |
---|
| 208 | + |
---|
| 209 | +static void ena_get_ethtool_stats(struct net_device *netdev, |
---|
| 210 | + struct ethtool_stats *stats, |
---|
| 211 | + u64 *data) |
---|
| 212 | +{ |
---|
| 213 | + struct ena_adapter *adapter = netdev_priv(netdev); |
---|
| 214 | + |
---|
| 215 | + ena_get_stats(adapter, data, adapter->eni_stats_supported); |
---|
| 216 | +} |
---|
| 217 | + |
---|
| 218 | +static int ena_get_sw_stats_count(struct ena_adapter *adapter) |
---|
| 219 | +{ |
---|
| 220 | + return adapter->num_io_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX) |
---|
| 221 | + + adapter->xdp_num_queues * ENA_STATS_ARRAY_TX |
---|
| 222 | + + ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM; |
---|
| 223 | +} |
---|
| 224 | + |
---|
| 225 | +static int ena_get_hw_stats_count(struct ena_adapter *adapter) |
---|
| 226 | +{ |
---|
| 227 | + return ENA_STATS_ARRAY_ENI(adapter); |
---|
196 | 228 | } |
---|
197 | 229 | |
---|
198 | 230 | int ena_get_sset_count(struct net_device *netdev, int sset) |
---|
.. | .. |
---|
202 | 234 | if (sset != ETH_SS_STATS) |
---|
203 | 235 | return -EOPNOTSUPP; |
---|
204 | 236 | |
---|
205 | | - return adapter->num_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX) |
---|
206 | | - + ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM; |
---|
| 237 | + return ena_get_sw_stats_count(adapter) + ena_get_hw_stats_count(adapter); |
---|
207 | 238 | } |
---|
208 | 239 | |
---|
209 | 240 | static void ena_queue_strings(struct ena_adapter *adapter, u8 **data) |
---|
210 | 241 | { |
---|
211 | 242 | const struct ena_stats *ena_stats; |
---|
| 243 | + bool is_xdp; |
---|
212 | 244 | int i, j; |
---|
213 | 245 | |
---|
214 | | - for (i = 0; i < adapter->num_queues; i++) { |
---|
| 246 | + for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) { |
---|
| 247 | + is_xdp = ENA_IS_XDP_INDEX(adapter, i); |
---|
215 | 248 | /* Tx stats */ |
---|
216 | 249 | for (j = 0; j < ENA_STATS_ARRAY_TX; j++) { |
---|
217 | 250 | ena_stats = &ena_stats_tx_strings[j]; |
---|
218 | 251 | |
---|
219 | 252 | snprintf(*data, ETH_GSTRING_LEN, |
---|
220 | | - "queue_%u_tx_%s", i, ena_stats->name); |
---|
221 | | - (*data) += ETH_GSTRING_LEN; |
---|
222 | | - } |
---|
223 | | - /* Rx stats */ |
---|
224 | | - for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { |
---|
225 | | - ena_stats = &ena_stats_rx_strings[j]; |
---|
226 | | - |
---|
227 | | - snprintf(*data, ETH_GSTRING_LEN, |
---|
228 | | - "queue_%u_rx_%s", i, ena_stats->name); |
---|
| 253 | + "queue_%u_%s_%s", i, |
---|
| 254 | + is_xdp ? "xdp_tx" : "tx", ena_stats->name); |
---|
229 | 255 | (*data) += ETH_GSTRING_LEN; |
---|
| 256 | + } |
---|
| 257 | + |
---|
| 258 | + if (!is_xdp) { |
---|
| 259 | + /* RX stats, in XDP there isn't a RX queue |
---|
| 260 | + * counterpart |
---|
| 261 | + */ |
---|
| 262 | + for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { |
---|
| 263 | + ena_stats = &ena_stats_rx_strings[j]; |
---|
| 264 | + |
---|
| 265 | + snprintf(*data, ETH_GSTRING_LEN, |
---|
| 266 | + "queue_%u_rx_%s", i, ena_stats->name); |
---|
| 267 | + (*data) += ETH_GSTRING_LEN; |
---|
| 268 | + } |
---|
230 | 269 | } |
---|
231 | 270 | } |
---|
232 | 271 | } |
---|
.. | .. |
---|
245 | 284 | } |
---|
246 | 285 | } |
---|
247 | 286 | |
---|
248 | | -static void ena_get_strings(struct net_device *netdev, u32 sset, u8 *data) |
---|
| 287 | +static void ena_get_strings(struct ena_adapter *adapter, |
---|
| 288 | + u8 *data, |
---|
| 289 | + bool eni_stats_needed) |
---|
249 | 290 | { |
---|
250 | | - struct ena_adapter *adapter = netdev_priv(netdev); |
---|
251 | 291 | const struct ena_stats *ena_stats; |
---|
252 | 292 | int i; |
---|
253 | 293 | |
---|
254 | | - if (sset != ETH_SS_STATS) |
---|
255 | | - return; |
---|
256 | | - |
---|
257 | 294 | for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) { |
---|
258 | 295 | ena_stats = &ena_stats_global_strings[i]; |
---|
259 | | - |
---|
260 | 296 | memcpy(data, ena_stats->name, ETH_GSTRING_LEN); |
---|
261 | 297 | data += ETH_GSTRING_LEN; |
---|
262 | 298 | } |
---|
263 | 299 | |
---|
| 300 | + if (eni_stats_needed) { |
---|
| 301 | + for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) { |
---|
| 302 | + ena_stats = &ena_stats_eni_strings[i]; |
---|
| 303 | + memcpy(data, ena_stats->name, ETH_GSTRING_LEN); |
---|
| 304 | + data += ETH_GSTRING_LEN; |
---|
| 305 | + } |
---|
| 306 | + } |
---|
| 307 | + |
---|
264 | 308 | ena_queue_strings(adapter, &data); |
---|
265 | 309 | ena_com_dev_strings(&data); |
---|
| 310 | +} |
---|
| 311 | + |
---|
| 312 | +static void ena_get_ethtool_strings(struct net_device *netdev, |
---|
| 313 | + u32 sset, |
---|
| 314 | + u8 *data) |
---|
| 315 | +{ |
---|
| 316 | + struct ena_adapter *adapter = netdev_priv(netdev); |
---|
| 317 | + |
---|
| 318 | + if (sset != ETH_SS_STATS) |
---|
| 319 | + return; |
---|
| 320 | + |
---|
| 321 | + ena_get_strings(adapter, data, adapter->eni_stats_supported); |
---|
266 | 322 | } |
---|
267 | 323 | |
---|
268 | 324 | static int ena_get_link_ksettings(struct net_device *netdev, |
---|
.. | .. |
---|
302 | 358 | { |
---|
303 | 359 | struct ena_adapter *adapter = netdev_priv(net_dev); |
---|
304 | 360 | struct ena_com_dev *ena_dev = adapter->ena_dev; |
---|
305 | | - struct ena_intr_moder_entry intr_moder_entry; |
---|
306 | 361 | |
---|
307 | | - if (!ena_com_interrupt_moderation_supported(ena_dev)) { |
---|
308 | | - /* the devie doesn't support interrupt moderation */ |
---|
| 362 | + if (!ena_com_interrupt_moderation_supported(ena_dev)) |
---|
309 | 363 | return -EOPNOTSUPP; |
---|
310 | | - } |
---|
| 364 | + |
---|
311 | 365 | coalesce->tx_coalesce_usecs = |
---|
312 | | - ena_com_get_nonadaptive_moderation_interval_tx(ena_dev) / |
---|
| 366 | + ena_com_get_nonadaptive_moderation_interval_tx(ena_dev) * |
---|
313 | 367 | ena_dev->intr_delay_resolution; |
---|
314 | | - if (!ena_com_get_adaptive_moderation_enabled(ena_dev)) { |
---|
315 | | - coalesce->rx_coalesce_usecs = |
---|
316 | | - ena_com_get_nonadaptive_moderation_interval_rx(ena_dev) |
---|
317 | | - / ena_dev->intr_delay_resolution; |
---|
318 | | - } else { |
---|
319 | | - ena_com_get_intr_moderation_entry(adapter->ena_dev, ENA_INTR_MODER_LOWEST, &intr_moder_entry); |
---|
320 | | - coalesce->rx_coalesce_usecs_low = intr_moder_entry.intr_moder_interval; |
---|
321 | | - coalesce->rx_max_coalesced_frames_low = intr_moder_entry.pkts_per_interval; |
---|
322 | 368 | |
---|
323 | | - ena_com_get_intr_moderation_entry(adapter->ena_dev, ENA_INTR_MODER_MID, &intr_moder_entry); |
---|
324 | | - coalesce->rx_coalesce_usecs = intr_moder_entry.intr_moder_interval; |
---|
325 | | - coalesce->rx_max_coalesced_frames = intr_moder_entry.pkts_per_interval; |
---|
| 369 | + coalesce->rx_coalesce_usecs = |
---|
| 370 | + ena_com_get_nonadaptive_moderation_interval_rx(ena_dev) |
---|
| 371 | + * ena_dev->intr_delay_resolution; |
---|
326 | 372 | |
---|
327 | | - ena_com_get_intr_moderation_entry(adapter->ena_dev, ENA_INTR_MODER_HIGHEST, &intr_moder_entry); |
---|
328 | | - coalesce->rx_coalesce_usecs_high = intr_moder_entry.intr_moder_interval; |
---|
329 | | - coalesce->rx_max_coalesced_frames_high = intr_moder_entry.pkts_per_interval; |
---|
330 | | - } |
---|
331 | 373 | coalesce->use_adaptive_rx_coalesce = |
---|
332 | 374 | ena_com_get_adaptive_moderation_enabled(ena_dev); |
---|
333 | 375 | |
---|
334 | 376 | return 0; |
---|
335 | 377 | } |
---|
336 | 378 | |
---|
337 | | -static void ena_update_tx_rings_intr_moderation(struct ena_adapter *adapter) |
---|
| 379 | +static void ena_update_tx_rings_nonadaptive_intr_moderation(struct ena_adapter *adapter) |
---|
338 | 380 | { |
---|
339 | 381 | unsigned int val; |
---|
340 | 382 | int i; |
---|
341 | 383 | |
---|
342 | 384 | val = ena_com_get_nonadaptive_moderation_interval_tx(adapter->ena_dev); |
---|
343 | 385 | |
---|
344 | | - for (i = 0; i < adapter->num_queues; i++) |
---|
| 386 | + for (i = 0; i < adapter->num_io_queues; i++) |
---|
345 | 387 | adapter->tx_ring[i].smoothed_interval = val; |
---|
| 388 | +} |
---|
| 389 | + |
---|
| 390 | +static void ena_update_rx_rings_nonadaptive_intr_moderation(struct ena_adapter *adapter) |
---|
| 391 | +{ |
---|
| 392 | + unsigned int val; |
---|
| 393 | + int i; |
---|
| 394 | + |
---|
| 395 | + val = ena_com_get_nonadaptive_moderation_interval_rx(adapter->ena_dev); |
---|
| 396 | + |
---|
| 397 | + for (i = 0; i < adapter->num_io_queues; i++) |
---|
| 398 | + adapter->rx_ring[i].smoothed_interval = val; |
---|
346 | 399 | } |
---|
347 | 400 | |
---|
348 | 401 | static int ena_set_coalesce(struct net_device *net_dev, |
---|
.. | .. |
---|
350 | 403 | { |
---|
351 | 404 | struct ena_adapter *adapter = netdev_priv(net_dev); |
---|
352 | 405 | struct ena_com_dev *ena_dev = adapter->ena_dev; |
---|
353 | | - struct ena_intr_moder_entry intr_moder_entry; |
---|
354 | 406 | int rc; |
---|
355 | 407 | |
---|
356 | | - if (!ena_com_interrupt_moderation_supported(ena_dev)) { |
---|
357 | | - /* the devie doesn't support interrupt moderation */ |
---|
| 408 | + if (!ena_com_interrupt_moderation_supported(ena_dev)) |
---|
358 | 409 | return -EOPNOTSUPP; |
---|
359 | | - } |
---|
360 | | - |
---|
361 | | - if (coalesce->rx_coalesce_usecs_irq || |
---|
362 | | - coalesce->rx_max_coalesced_frames_irq || |
---|
363 | | - coalesce->tx_coalesce_usecs_irq || |
---|
364 | | - coalesce->tx_max_coalesced_frames || |
---|
365 | | - coalesce->tx_max_coalesced_frames_irq || |
---|
366 | | - coalesce->stats_block_coalesce_usecs || |
---|
367 | | - coalesce->use_adaptive_tx_coalesce || |
---|
368 | | - coalesce->pkt_rate_low || |
---|
369 | | - coalesce->tx_coalesce_usecs_low || |
---|
370 | | - coalesce->tx_max_coalesced_frames_low || |
---|
371 | | - coalesce->pkt_rate_high || |
---|
372 | | - coalesce->tx_coalesce_usecs_high || |
---|
373 | | - coalesce->tx_max_coalesced_frames_high || |
---|
374 | | - coalesce->rate_sample_interval) |
---|
375 | | - return -EINVAL; |
---|
376 | 410 | |
---|
377 | 411 | rc = ena_com_update_nonadaptive_moderation_interval_tx(ena_dev, |
---|
378 | 412 | coalesce->tx_coalesce_usecs); |
---|
379 | 413 | if (rc) |
---|
380 | 414 | return rc; |
---|
381 | 415 | |
---|
382 | | - ena_update_tx_rings_intr_moderation(adapter); |
---|
| 416 | + ena_update_tx_rings_nonadaptive_intr_moderation(adapter); |
---|
383 | 417 | |
---|
384 | | - if (ena_com_get_adaptive_moderation_enabled(ena_dev)) { |
---|
385 | | - if (!coalesce->use_adaptive_rx_coalesce) { |
---|
386 | | - ena_com_disable_adaptive_moderation(ena_dev); |
---|
387 | | - rc = ena_com_update_nonadaptive_moderation_interval_rx(ena_dev, |
---|
388 | | - coalesce->rx_coalesce_usecs); |
---|
389 | | - return rc; |
---|
390 | | - } |
---|
391 | | - } else { /* was in non-adaptive mode */ |
---|
392 | | - if (coalesce->use_adaptive_rx_coalesce) { |
---|
393 | | - ena_com_enable_adaptive_moderation(ena_dev); |
---|
394 | | - } else { |
---|
395 | | - rc = ena_com_update_nonadaptive_moderation_interval_rx(ena_dev, |
---|
396 | | - coalesce->rx_coalesce_usecs); |
---|
397 | | - return rc; |
---|
398 | | - } |
---|
399 | | - } |
---|
| 418 | + rc = ena_com_update_nonadaptive_moderation_interval_rx(ena_dev, |
---|
| 419 | + coalesce->rx_coalesce_usecs); |
---|
| 420 | + if (rc) |
---|
| 421 | + return rc; |
---|
400 | 422 | |
---|
401 | | - intr_moder_entry.intr_moder_interval = coalesce->rx_coalesce_usecs_low; |
---|
402 | | - intr_moder_entry.pkts_per_interval = coalesce->rx_max_coalesced_frames_low; |
---|
403 | | - intr_moder_entry.bytes_per_interval = ENA_INTR_BYTE_COUNT_NOT_SUPPORTED; |
---|
404 | | - ena_com_init_intr_moderation_entry(adapter->ena_dev, ENA_INTR_MODER_LOWEST, &intr_moder_entry); |
---|
| 423 | + ena_update_rx_rings_nonadaptive_intr_moderation(adapter); |
---|
405 | 424 | |
---|
406 | | - intr_moder_entry.intr_moder_interval = coalesce->rx_coalesce_usecs; |
---|
407 | | - intr_moder_entry.pkts_per_interval = coalesce->rx_max_coalesced_frames; |
---|
408 | | - intr_moder_entry.bytes_per_interval = ENA_INTR_BYTE_COUNT_NOT_SUPPORTED; |
---|
409 | | - ena_com_init_intr_moderation_entry(adapter->ena_dev, ENA_INTR_MODER_MID, &intr_moder_entry); |
---|
| 425 | + if (coalesce->use_adaptive_rx_coalesce && |
---|
| 426 | + !ena_com_get_adaptive_moderation_enabled(ena_dev)) |
---|
| 427 | + ena_com_enable_adaptive_moderation(ena_dev); |
---|
410 | 428 | |
---|
411 | | - intr_moder_entry.intr_moder_interval = coalesce->rx_coalesce_usecs_high; |
---|
412 | | - intr_moder_entry.pkts_per_interval = coalesce->rx_max_coalesced_frames_high; |
---|
413 | | - intr_moder_entry.bytes_per_interval = ENA_INTR_BYTE_COUNT_NOT_SUPPORTED; |
---|
414 | | - ena_com_init_intr_moderation_entry(adapter->ena_dev, ENA_INTR_MODER_HIGHEST, &intr_moder_entry); |
---|
| 429 | + if (!coalesce->use_adaptive_rx_coalesce && |
---|
| 430 | + ena_com_get_adaptive_moderation_enabled(ena_dev)) |
---|
| 431 | + ena_com_disable_adaptive_moderation(ena_dev); |
---|
415 | 432 | |
---|
416 | 433 | return 0; |
---|
417 | 434 | } |
---|
.. | .. |
---|
436 | 453 | struct ena_adapter *adapter = netdev_priv(dev); |
---|
437 | 454 | |
---|
438 | 455 | strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver)); |
---|
439 | | - strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); |
---|
440 | 456 | strlcpy(info->bus_info, pci_name(adapter->pdev), |
---|
441 | 457 | sizeof(info->bus_info)); |
---|
442 | 458 | } |
---|
.. | .. |
---|
445 | 461 | struct ethtool_ringparam *ring) |
---|
446 | 462 | { |
---|
447 | 463 | struct ena_adapter *adapter = netdev_priv(netdev); |
---|
448 | | - struct ena_ring *tx_ring = &adapter->tx_ring[0]; |
---|
449 | | - struct ena_ring *rx_ring = &adapter->rx_ring[0]; |
---|
450 | 464 | |
---|
451 | | - ring->rx_max_pending = rx_ring->ring_size; |
---|
452 | | - ring->tx_max_pending = tx_ring->ring_size; |
---|
453 | | - ring->rx_pending = rx_ring->ring_size; |
---|
454 | | - ring->tx_pending = tx_ring->ring_size; |
---|
| 465 | + ring->tx_max_pending = adapter->max_tx_ring_size; |
---|
| 466 | + ring->rx_max_pending = adapter->max_rx_ring_size; |
---|
| 467 | + ring->tx_pending = adapter->tx_ring[0].ring_size; |
---|
| 468 | + ring->rx_pending = adapter->rx_ring[0].ring_size; |
---|
| 469 | +} |
---|
| 470 | + |
---|
| 471 | +static int ena_set_ringparam(struct net_device *netdev, |
---|
| 472 | + struct ethtool_ringparam *ring) |
---|
| 473 | +{ |
---|
| 474 | + struct ena_adapter *adapter = netdev_priv(netdev); |
---|
| 475 | + u32 new_tx_size, new_rx_size; |
---|
| 476 | + |
---|
| 477 | + new_tx_size = ring->tx_pending < ENA_MIN_RING_SIZE ? |
---|
| 478 | + ENA_MIN_RING_SIZE : ring->tx_pending; |
---|
| 479 | + new_tx_size = rounddown_pow_of_two(new_tx_size); |
---|
| 480 | + |
---|
| 481 | + new_rx_size = ring->rx_pending < ENA_MIN_RING_SIZE ? |
---|
| 482 | + ENA_MIN_RING_SIZE : ring->rx_pending; |
---|
| 483 | + new_rx_size = rounddown_pow_of_two(new_rx_size); |
---|
| 484 | + |
---|
| 485 | + if (new_tx_size == adapter->requested_tx_ring_size && |
---|
| 486 | + new_rx_size == adapter->requested_rx_ring_size) |
---|
| 487 | + return 0; |
---|
| 488 | + |
---|
| 489 | + return ena_update_queue_sizes(adapter, new_tx_size, new_rx_size); |
---|
455 | 490 | } |
---|
456 | 491 | |
---|
457 | 492 | static u32 ena_flow_hash_to_flow_type(u16 hash_fields) |
---|
.. | .. |
---|
621 | 656 | |
---|
622 | 657 | switch (info->cmd) { |
---|
623 | 658 | case ETHTOOL_GRXRINGS: |
---|
624 | | - info->data = adapter->num_queues; |
---|
| 659 | + info->data = adapter->num_io_queues; |
---|
625 | 660 | rc = 0; |
---|
626 | 661 | break; |
---|
627 | 662 | case ETHTOOL_GRXFH: |
---|
.. | .. |
---|
647 | 682 | static u32 ena_get_rxfh_key_size(struct net_device *netdev) |
---|
648 | 683 | { |
---|
649 | 684 | return ENA_HASH_KEY_SIZE; |
---|
| 685 | +} |
---|
| 686 | + |
---|
| 687 | +static int ena_indirection_table_set(struct ena_adapter *adapter, |
---|
| 688 | + const u32 *indir) |
---|
| 689 | +{ |
---|
| 690 | + struct ena_com_dev *ena_dev = adapter->ena_dev; |
---|
| 691 | + int i, rc; |
---|
| 692 | + |
---|
| 693 | + for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) { |
---|
| 694 | + rc = ena_com_indirect_table_fill_entry(ena_dev, |
---|
| 695 | + i, |
---|
| 696 | + ENA_IO_RXQ_IDX(indir[i])); |
---|
| 697 | + if (unlikely(rc)) { |
---|
| 698 | + netif_err(adapter, drv, adapter->netdev, |
---|
| 699 | + "Cannot fill indirect table (index is too large)\n"); |
---|
| 700 | + return rc; |
---|
| 701 | + } |
---|
| 702 | + } |
---|
| 703 | + |
---|
| 704 | + rc = ena_com_indirect_table_set(ena_dev); |
---|
| 705 | + if (rc) { |
---|
| 706 | + netif_err(adapter, drv, adapter->netdev, |
---|
| 707 | + "Cannot set indirect table\n"); |
---|
| 708 | + return rc == -EPERM ? -EOPNOTSUPP : rc; |
---|
| 709 | + } |
---|
| 710 | + return rc; |
---|
650 | 711 | } |
---|
651 | 712 | |
---|
652 | 713 | static int ena_indirection_table_get(struct ena_adapter *adapter, u32 *indir) |
---|
.. | .. |
---|
686 | 747 | /* We call this function in order to check if the device |
---|
687 | 748 | * supports getting/setting the hash function. |
---|
688 | 749 | */ |
---|
689 | | - rc = ena_com_get_hash_function(adapter->ena_dev, &ena_func, key); |
---|
690 | | - |
---|
| 750 | + rc = ena_com_get_hash_function(adapter->ena_dev, &ena_func); |
---|
691 | 751 | if (rc) { |
---|
692 | | - if (rc == -EOPNOTSUPP) { |
---|
693 | | - key = NULL; |
---|
694 | | - hfunc = NULL; |
---|
| 752 | + if (rc == -EOPNOTSUPP) |
---|
695 | 753 | rc = 0; |
---|
696 | | - } |
---|
697 | 754 | |
---|
698 | 755 | return rc; |
---|
699 | 756 | } |
---|
700 | 757 | |
---|
| 758 | + rc = ena_com_get_hash_key(adapter->ena_dev, key); |
---|
701 | 759 | if (rc) |
---|
702 | 760 | return rc; |
---|
703 | 761 | |
---|
.. | .. |
---|
717 | 775 | if (hfunc) |
---|
718 | 776 | *hfunc = func; |
---|
719 | 777 | |
---|
720 | | - return rc; |
---|
| 778 | + return 0; |
---|
721 | 779 | } |
---|
722 | 780 | |
---|
723 | 781 | static int ena_set_rxfh(struct net_device *netdev, const u32 *indir, |
---|
.. | .. |
---|
725 | 783 | { |
---|
726 | 784 | struct ena_adapter *adapter = netdev_priv(netdev); |
---|
727 | 785 | struct ena_com_dev *ena_dev = adapter->ena_dev; |
---|
728 | | - enum ena_admin_hash_functions func; |
---|
729 | | - int rc, i; |
---|
| 786 | + enum ena_admin_hash_functions func = 0; |
---|
| 787 | + int rc; |
---|
730 | 788 | |
---|
731 | 789 | if (indir) { |
---|
732 | | - for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) { |
---|
733 | | - rc = ena_com_indirect_table_fill_entry(ena_dev, |
---|
734 | | - i, |
---|
735 | | - ENA_IO_RXQ_IDX(indir[i])); |
---|
736 | | - if (unlikely(rc)) { |
---|
737 | | - netif_err(adapter, drv, netdev, |
---|
738 | | - "Cannot fill indirect table (index is too large)\n"); |
---|
739 | | - return rc; |
---|
740 | | - } |
---|
741 | | - } |
---|
742 | | - |
---|
743 | | - rc = ena_com_indirect_table_set(ena_dev); |
---|
744 | | - if (rc) { |
---|
745 | | - netif_err(adapter, drv, netdev, |
---|
746 | | - "Cannot set indirect table\n"); |
---|
747 | | - return rc == -EPERM ? -EOPNOTSUPP : rc; |
---|
748 | | - } |
---|
| 790 | + rc = ena_indirection_table_set(adapter, indir); |
---|
| 791 | + if (rc) |
---|
| 792 | + return rc; |
---|
749 | 793 | } |
---|
750 | 794 | |
---|
751 | 795 | switch (hfunc) { |
---|
.. | .. |
---|
764 | 808 | return -EOPNOTSUPP; |
---|
765 | 809 | } |
---|
766 | 810 | |
---|
767 | | - if (key) { |
---|
| 811 | + if (key || func) { |
---|
768 | 812 | rc = ena_com_fill_hash_function(ena_dev, func, key, |
---|
769 | 813 | ENA_HASH_KEY_SIZE, |
---|
770 | 814 | 0xFFFFFFFF); |
---|
.. | .. |
---|
782 | 826 | { |
---|
783 | 827 | struct ena_adapter *adapter = netdev_priv(netdev); |
---|
784 | 828 | |
---|
785 | | - channels->max_rx = adapter->num_queues; |
---|
786 | | - channels->max_tx = adapter->num_queues; |
---|
787 | | - channels->max_other = 0; |
---|
788 | | - channels->max_combined = 0; |
---|
789 | | - channels->rx_count = adapter->num_queues; |
---|
790 | | - channels->tx_count = adapter->num_queues; |
---|
791 | | - channels->other_count = 0; |
---|
792 | | - channels->combined_count = 0; |
---|
| 829 | + channels->max_combined = adapter->max_num_io_queues; |
---|
| 830 | + channels->combined_count = adapter->num_io_queues; |
---|
| 831 | +} |
---|
| 832 | + |
---|
| 833 | +static int ena_set_channels(struct net_device *netdev, |
---|
| 834 | + struct ethtool_channels *channels) |
---|
| 835 | +{ |
---|
| 836 | + struct ena_adapter *adapter = netdev_priv(netdev); |
---|
| 837 | + u32 count = channels->combined_count; |
---|
| 838 | + /* The check for max value is already done in ethtool */ |
---|
| 839 | + if (count < ENA_MIN_NUM_IO_QUEUES || |
---|
| 840 | + (ena_xdp_present(adapter) && |
---|
| 841 | + !ena_xdp_legal_queue_count(adapter, channels->combined_count))) |
---|
| 842 | + return -EINVAL; |
---|
| 843 | + |
---|
| 844 | + return ena_update_queue_count(adapter, count); |
---|
793 | 845 | } |
---|
794 | 846 | |
---|
795 | 847 | static int ena_get_tunable(struct net_device *netdev, |
---|
.. | .. |
---|
836 | 888 | } |
---|
837 | 889 | |
---|
838 | 890 | static const struct ethtool_ops ena_ethtool_ops = { |
---|
| 891 | + .supported_coalesce_params = ETHTOOL_COALESCE_USECS | |
---|
| 892 | + ETHTOOL_COALESCE_USE_ADAPTIVE_RX, |
---|
839 | 893 | .get_link_ksettings = ena_get_link_ksettings, |
---|
840 | 894 | .get_drvinfo = ena_get_drvinfo, |
---|
841 | 895 | .get_msglevel = ena_get_msglevel, |
---|
.. | .. |
---|
844 | 898 | .get_coalesce = ena_get_coalesce, |
---|
845 | 899 | .set_coalesce = ena_set_coalesce, |
---|
846 | 900 | .get_ringparam = ena_get_ringparam, |
---|
| 901 | + .set_ringparam = ena_set_ringparam, |
---|
847 | 902 | .get_sset_count = ena_get_sset_count, |
---|
848 | | - .get_strings = ena_get_strings, |
---|
| 903 | + .get_strings = ena_get_ethtool_strings, |
---|
849 | 904 | .get_ethtool_stats = ena_get_ethtool_stats, |
---|
850 | 905 | .get_rxnfc = ena_get_rxnfc, |
---|
851 | 906 | .set_rxnfc = ena_set_rxnfc, |
---|
.. | .. |
---|
854 | 909 | .get_rxfh = ena_get_rxfh, |
---|
855 | 910 | .set_rxfh = ena_set_rxfh, |
---|
856 | 911 | .get_channels = ena_get_channels, |
---|
| 912 | + .set_channels = ena_set_channels, |
---|
857 | 913 | .get_tunable = ena_get_tunable, |
---|
858 | 914 | .set_tunable = ena_set_tunable, |
---|
859 | 915 | .get_ts_info = ethtool_op_get_ts_info, |
---|
.. | .. |
---|
872 | 928 | int strings_num; |
---|
873 | 929 | int i, rc; |
---|
874 | 930 | |
---|
875 | | - strings_num = ena_get_sset_count(netdev, ETH_SS_STATS); |
---|
| 931 | + strings_num = ena_get_sw_stats_count(adapter); |
---|
876 | 932 | if (strings_num <= 0) { |
---|
877 | 933 | netif_err(adapter, drv, netdev, "Can't get stats num\n"); |
---|
878 | 934 | return; |
---|
.. | .. |
---|
883 | 939 | GFP_ATOMIC); |
---|
884 | 940 | if (!strings_buf) { |
---|
885 | 941 | netif_err(adapter, drv, netdev, |
---|
886 | | - "failed to alloc strings_buf\n"); |
---|
| 942 | + "Failed to allocate strings_buf\n"); |
---|
887 | 943 | return; |
---|
888 | 944 | } |
---|
889 | 945 | |
---|
.. | .. |
---|
892 | 948 | GFP_ATOMIC); |
---|
893 | 949 | if (!data_buf) { |
---|
894 | 950 | netif_err(adapter, drv, netdev, |
---|
895 | | - "failed to allocate data buf\n"); |
---|
| 951 | + "Failed to allocate data buf\n"); |
---|
896 | 952 | devm_kfree(&adapter->pdev->dev, strings_buf); |
---|
897 | 953 | return; |
---|
898 | 954 | } |
---|
899 | 955 | |
---|
900 | | - ena_get_strings(netdev, ETH_SS_STATS, strings_buf); |
---|
901 | | - ena_get_ethtool_stats(netdev, NULL, data_buf); |
---|
| 956 | + ena_get_strings(adapter, strings_buf, false); |
---|
| 957 | + ena_get_stats(adapter, data_buf, false); |
---|
902 | 958 | |
---|
903 | 959 | /* If there is a buffer, dump stats, otherwise print them to dmesg */ |
---|
904 | 960 | if (buf) |
---|