.. | .. |
---|
5 | 5 | |
---|
6 | 6 | #include "i40e.h" |
---|
7 | 7 | #include "i40e_diag.h" |
---|
| 8 | +#include "i40e_txrx_common.h" |
---|
8 | 9 | |
---|
| 10 | +/* ethtool statistics helpers */ |
---|
| 11 | + |
---|
| 12 | +/** |
---|
| 13 | + * struct i40e_stats - definition for an ethtool statistic |
---|
| 14 | + * @stat_string: statistic name to display in ethtool -S output |
---|
| 15 | + * @sizeof_stat: the sizeof() the stat, must be no greater than sizeof(u64) |
---|
| 16 | + * @stat_offset: offsetof() the stat from a base pointer |
---|
| 17 | + * |
---|
| 18 | + * This structure defines a statistic to be added to the ethtool stats buffer. |
---|
| 19 | + * It defines a statistic as offset from a common base pointer. Stats should |
---|
| 20 | + * be defined in constant arrays using the I40E_STAT macro, with every element |
---|
| 21 | + * of the array using the same _type for calculating the sizeof_stat and |
---|
| 22 | + * stat_offset. |
---|
| 23 | + * |
---|
| 24 | + * The @sizeof_stat is expected to be sizeof(u8), sizeof(u16), sizeof(u32) or |
---|
| 25 | + * sizeof(u64). Other sizes are not expected and will produce a WARN_ONCE from |
---|
| 26 | + * the i40e_add_ethtool_stat() helper function. |
---|
| 27 | + * |
---|
| 28 | + * The @stat_string is interpreted as a format string, allowing formatted |
---|
| 29 | + * values to be inserted while looping over multiple structures for a given |
---|
| 30 | + * statistics array. Thus, every statistic string in an array should have the |
---|
| 31 | + * same type and number of format specifiers, to be formatted by variadic |
---|
| 32 | + * arguments to the i40e_add_stat_string() helper function. |
---|
| 33 | + **/ |
---|
9 | 34 | struct i40e_stats { |
---|
10 | | - /* The stat_string is expected to be a format string formatted using |
---|
11 | | - * vsnprintf by i40e_add_stat_strings. Every member of a stats array |
---|
12 | | - * should use the same format specifiers as they will be formatted |
---|
13 | | - * using the same variadic arguments. |
---|
14 | | - */ |
---|
15 | 35 | char stat_string[ETH_GSTRING_LEN]; |
---|
16 | 36 | int sizeof_stat; |
---|
17 | 37 | int stat_offset; |
---|
18 | 38 | }; |
---|
19 | 39 | |
---|
| 40 | +/* Helper macro to define an i40e_stat structure with proper size and type. |
---|
| 41 | + * Use this when defining constant statistics arrays. Note that @_type expects |
---|
| 42 | + * only a type name and is used multiple times. |
---|
| 43 | + */ |
---|
20 | 44 | #define I40E_STAT(_type, _name, _stat) { \ |
---|
21 | 45 | .stat_string = _name, \ |
---|
22 | | - .sizeof_stat = FIELD_SIZEOF(_type, _stat), \ |
---|
| 46 | + .sizeof_stat = sizeof_field(_type, _stat), \ |
---|
23 | 47 | .stat_offset = offsetof(_type, _stat) \ |
---|
24 | 48 | } |
---|
25 | 49 | |
---|
| 50 | +/* Helper macro for defining some statistics directly copied from the netdev |
---|
| 51 | + * stats structure. |
---|
| 52 | + */ |
---|
26 | 53 | #define I40E_NETDEV_STAT(_net_stat) \ |
---|
27 | 54 | I40E_STAT(struct rtnl_link_stats64, #_net_stat, _net_stat) |
---|
| 55 | + |
---|
| 56 | +/* Helper macro for defining some statistics related to queues */ |
---|
| 57 | +#define I40E_QUEUE_STAT(_name, _stat) \ |
---|
| 58 | + I40E_STAT(struct i40e_ring, _name, _stat) |
---|
| 59 | + |
---|
| 60 | +/* Stats associated with a Tx or Rx ring */ |
---|
| 61 | +static const struct i40e_stats i40e_gstrings_queue_stats[] = { |
---|
| 62 | + I40E_QUEUE_STAT("%s-%u.packets", stats.packets), |
---|
| 63 | + I40E_QUEUE_STAT("%s-%u.bytes", stats.bytes), |
---|
| 64 | +}; |
---|
| 65 | + |
---|
| 66 | +/** |
---|
| 67 | + * i40e_add_one_ethtool_stat - copy the stat into the supplied buffer |
---|
| 68 | + * @data: location to store the stat value |
---|
| 69 | + * @pointer: basis for where to copy from |
---|
| 70 | + * @stat: the stat definition |
---|
| 71 | + * |
---|
| 72 | + * Copies the stat data defined by the pointer and stat structure pair into |
---|
| 73 | + * the memory supplied as data. Used to implement i40e_add_ethtool_stats and |
---|
| 74 | + * i40e_add_queue_stats. If the pointer is null, data will be zero'd. |
---|
| 75 | + */ |
---|
| 76 | +static void |
---|
| 77 | +i40e_add_one_ethtool_stat(u64 *data, void *pointer, |
---|
| 78 | + const struct i40e_stats *stat) |
---|
| 79 | +{ |
---|
| 80 | + char *p; |
---|
| 81 | + |
---|
| 82 | + if (!pointer) { |
---|
| 83 | + /* ensure that the ethtool data buffer is zero'd for any stats |
---|
| 84 | + * which don't have a valid pointer. |
---|
| 85 | + */ |
---|
| 86 | + *data = 0; |
---|
| 87 | + return; |
---|
| 88 | + } |
---|
| 89 | + |
---|
| 90 | + p = (char *)pointer + stat->stat_offset; |
---|
| 91 | + switch (stat->sizeof_stat) { |
---|
| 92 | + case sizeof(u64): |
---|
| 93 | + *data = *((u64 *)p); |
---|
| 94 | + break; |
---|
| 95 | + case sizeof(u32): |
---|
| 96 | + *data = *((u32 *)p); |
---|
| 97 | + break; |
---|
| 98 | + case sizeof(u16): |
---|
| 99 | + *data = *((u16 *)p); |
---|
| 100 | + break; |
---|
| 101 | + case sizeof(u8): |
---|
| 102 | + *data = *((u8 *)p); |
---|
| 103 | + break; |
---|
| 104 | + default: |
---|
| 105 | + WARN_ONCE(1, "unexpected stat size for %s", |
---|
| 106 | + stat->stat_string); |
---|
| 107 | + *data = 0; |
---|
| 108 | + } |
---|
| 109 | +} |
---|
| 110 | + |
---|
| 111 | +/** |
---|
| 112 | + * __i40e_add_ethtool_stats - copy stats into the ethtool supplied buffer |
---|
| 113 | + * @data: ethtool stats buffer |
---|
| 114 | + * @pointer: location to copy stats from |
---|
| 115 | + * @stats: array of stats to copy |
---|
| 116 | + * @size: the size of the stats definition |
---|
| 117 | + * |
---|
| 118 | + * Copy the stats defined by the stats array using the pointer as a base into |
---|
| 119 | + * the data buffer supplied by ethtool. Updates the data pointer to point to |
---|
| 120 | + * the next empty location for successive calls to __i40e_add_ethtool_stats. |
---|
| 121 | + * If pointer is null, set the data values to zero and update the pointer to |
---|
| 122 | + * skip these stats. |
---|
| 123 | + **/ |
---|
| 124 | +static void |
---|
| 125 | +__i40e_add_ethtool_stats(u64 **data, void *pointer, |
---|
| 126 | + const struct i40e_stats stats[], |
---|
| 127 | + const unsigned int size) |
---|
| 128 | +{ |
---|
| 129 | + unsigned int i; |
---|
| 130 | + |
---|
| 131 | + for (i = 0; i < size; i++) |
---|
| 132 | + i40e_add_one_ethtool_stat((*data)++, pointer, &stats[i]); |
---|
| 133 | +} |
---|
| 134 | + |
---|
| 135 | +/** |
---|
| 136 | + * i40e_add_ethtool_stats - copy stats into ethtool supplied buffer |
---|
| 137 | + * @data: ethtool stats buffer |
---|
| 138 | + * @pointer: location where stats are stored |
---|
| 139 | + * @stats: static const array of stat definitions |
---|
| 140 | + * |
---|
| 141 | + * Macro to ease the use of __i40e_add_ethtool_stats by taking a static |
---|
| 142 | + * constant stats array and passing the ARRAY_SIZE(). This avoids typos by |
---|
| 143 | + * ensuring that we pass the size associated with the given stats array. |
---|
| 144 | + * |
---|
| 145 | + * The parameter @stats is evaluated twice, so parameters with side effects |
---|
| 146 | + * should be avoided. |
---|
| 147 | + **/ |
---|
| 148 | +#define i40e_add_ethtool_stats(data, pointer, stats) \ |
---|
| 149 | + __i40e_add_ethtool_stats(data, pointer, stats, ARRAY_SIZE(stats)) |
---|
| 150 | + |
---|
| 151 | +/** |
---|
| 152 | + * i40e_add_queue_stats - copy queue statistics into supplied buffer |
---|
| 153 | + * @data: ethtool stats buffer |
---|
| 154 | + * @ring: the ring to copy |
---|
| 155 | + * |
---|
| 156 | + * Queue statistics must be copied while protected by |
---|
| 157 | + * u64_stats_fetch_begin_irq, so we can't directly use i40e_add_ethtool_stats. |
---|
| 158 | + * Assumes that queue stats are defined in i40e_gstrings_queue_stats. If the |
---|
| 159 | + * ring pointer is null, zero out the queue stat values and update the data |
---|
| 160 | + * pointer. Otherwise safely copy the stats from the ring into the supplied |
---|
| 161 | + * buffer and update the data pointer when finished. |
---|
| 162 | + * |
---|
| 163 | + * This function expects to be called while under rcu_read_lock(). |
---|
| 164 | + **/ |
---|
| 165 | +static void |
---|
| 166 | +i40e_add_queue_stats(u64 **data, struct i40e_ring *ring) |
---|
| 167 | +{ |
---|
| 168 | + const unsigned int size = ARRAY_SIZE(i40e_gstrings_queue_stats); |
---|
| 169 | + const struct i40e_stats *stats = i40e_gstrings_queue_stats; |
---|
| 170 | + unsigned int start; |
---|
| 171 | + unsigned int i; |
---|
| 172 | + |
---|
| 173 | + /* To avoid invalid statistics values, ensure that we keep retrying |
---|
| 174 | + * the copy until we get a consistent value according to |
---|
| 175 | + * u64_stats_fetch_retry_irq. But first, make sure our ring is |
---|
| 176 | + * non-null before attempting to access its syncp. |
---|
| 177 | + */ |
---|
| 178 | + do { |
---|
| 179 | + start = !ring ? 0 : u64_stats_fetch_begin_irq(&ring->syncp); |
---|
| 180 | + for (i = 0; i < size; i++) { |
---|
| 181 | + i40e_add_one_ethtool_stat(&(*data)[i], ring, |
---|
| 182 | + &stats[i]); |
---|
| 183 | + } |
---|
| 184 | + } while (ring && u64_stats_fetch_retry_irq(&ring->syncp, start)); |
---|
| 185 | + |
---|
| 186 | + /* Once we successfully copy the stats in, update the data pointer */ |
---|
| 187 | + *data += size; |
---|
| 188 | +} |
---|
| 189 | + |
---|
| 190 | +/** |
---|
| 191 | + * __i40e_add_stat_strings - copy stat strings into ethtool buffer |
---|
| 192 | + * @p: ethtool supplied buffer |
---|
| 193 | + * @stats: stat definitions array |
---|
| 194 | + * @size: size of the stats array |
---|
| 195 | + * |
---|
| 196 | + * Format and copy the strings described by stats into the buffer pointed at |
---|
| 197 | + * by p. |
---|
| 198 | + **/ |
---|
| 199 | +static void __i40e_add_stat_strings(u8 **p, const struct i40e_stats stats[], |
---|
| 200 | + const unsigned int size, ...) |
---|
| 201 | +{ |
---|
| 202 | + unsigned int i; |
---|
| 203 | + |
---|
| 204 | + for (i = 0; i < size; i++) { |
---|
| 205 | + va_list args; |
---|
| 206 | + |
---|
| 207 | + va_start(args, size); |
---|
| 208 | + vsnprintf(*p, ETH_GSTRING_LEN, stats[i].stat_string, args); |
---|
| 209 | + *p += ETH_GSTRING_LEN; |
---|
| 210 | + va_end(args); |
---|
| 211 | + } |
---|
| 212 | +} |
---|
| 213 | + |
---|
| 214 | +/** |
---|
| 215 | + * 40e_add_stat_strings - copy stat strings into ethtool buffer |
---|
| 216 | + * @p: ethtool supplied buffer |
---|
| 217 | + * @stats: stat definitions array |
---|
| 218 | + * |
---|
| 219 | + * Format and copy the strings described by the const static stats value into |
---|
| 220 | + * the buffer pointed at by p. |
---|
| 221 | + * |
---|
| 222 | + * The parameter @stats is evaluated twice, so parameters with side effects |
---|
| 223 | + * should be avoided. Additionally, stats must be an array such that |
---|
| 224 | + * ARRAY_SIZE can be called on it. |
---|
| 225 | + **/ |
---|
| 226 | +#define i40e_add_stat_strings(p, stats, ...) \ |
---|
| 227 | + __i40e_add_stat_strings(p, stats, ARRAY_SIZE(stats), ## __VA_ARGS__) |
---|
| 228 | + |
---|
28 | 229 | #define I40E_PF_STAT(_name, _stat) \ |
---|
29 | 230 | I40E_STAT(struct i40e_pf, _name, _stat) |
---|
30 | 231 | #define I40E_VSI_STAT(_name, _stat) \ |
---|
31 | 232 | I40E_STAT(struct i40e_vsi, _name, _stat) |
---|
32 | 233 | #define I40E_VEB_STAT(_name, _stat) \ |
---|
33 | 234 | I40E_STAT(struct i40e_veb, _name, _stat) |
---|
| 235 | +#define I40E_VEB_TC_STAT(_name, _stat) \ |
---|
| 236 | + I40E_STAT(struct i40e_cp_veb_tc_stats, _name, _stat) |
---|
34 | 237 | #define I40E_PFC_STAT(_name, _stat) \ |
---|
35 | 238 | I40E_STAT(struct i40e_pfc_stats, _name, _stat) |
---|
| 239 | +#define I40E_QUEUE_STAT(_name, _stat) \ |
---|
| 240 | + I40E_STAT(struct i40e_ring, _name, _stat) |
---|
36 | 241 | |
---|
37 | 242 | static const struct i40e_stats i40e_gstrings_net_stats[] = { |
---|
38 | 243 | I40E_NETDEV_STAT(rx_packets), |
---|
.. | .. |
---|
63 | 268 | I40E_VEB_STAT("veb.rx_unknown_protocol", stats.rx_unknown_protocol), |
---|
64 | 269 | }; |
---|
65 | 270 | |
---|
| 271 | +struct i40e_cp_veb_tc_stats { |
---|
| 272 | + u64 tc_rx_packets; |
---|
| 273 | + u64 tc_rx_bytes; |
---|
| 274 | + u64 tc_tx_packets; |
---|
| 275 | + u64 tc_tx_bytes; |
---|
| 276 | +}; |
---|
| 277 | + |
---|
66 | 278 | static const struct i40e_stats i40e_gstrings_veb_tc_stats[] = { |
---|
67 | | - I40E_VEB_STAT("veb.tc_%u_tx_packets", tc_stats.tc_tx_packets), |
---|
68 | | - I40E_VEB_STAT("veb.tc_%u_tx_bytes", tc_stats.tc_tx_bytes), |
---|
69 | | - I40E_VEB_STAT("veb.tc_%u_rx_packets", tc_stats.tc_rx_packets), |
---|
70 | | - I40E_VEB_STAT("veb.tc_%u_rx_bytes", tc_stats.tc_rx_bytes), |
---|
| 279 | + I40E_VEB_TC_STAT("veb.tc_%u_tx_packets", tc_tx_packets), |
---|
| 280 | + I40E_VEB_TC_STAT("veb.tc_%u_tx_bytes", tc_tx_bytes), |
---|
| 281 | + I40E_VEB_TC_STAT("veb.tc_%u_rx_packets", tc_rx_packets), |
---|
| 282 | + I40E_VEB_TC_STAT("veb.tc_%u_rx_bytes", tc_rx_bytes), |
---|
71 | 283 | }; |
---|
72 | 284 | |
---|
73 | 285 | static const struct i40e_stats i40e_gstrings_misc_stats[] = { |
---|
.. | .. |
---|
171 | 383 | I40E_PFC_STAT("port.rx_priority_%u_xon_2_xoff", priority_xon_2_xoff), |
---|
172 | 384 | }; |
---|
173 | 385 | |
---|
174 | | -/* We use num_tx_queues here as a proxy for the maximum number of queues |
---|
175 | | - * available because we always allocate queues symmetrically. |
---|
176 | | - */ |
---|
177 | | -#define I40E_MAX_NUM_QUEUES(n) ((n)->num_tx_queues) |
---|
178 | | -#define I40E_QUEUE_STATS_LEN(n) \ |
---|
179 | | - (I40E_MAX_NUM_QUEUES(n) \ |
---|
180 | | - * 2 /* Tx and Rx together */ \ |
---|
181 | | - * (sizeof(struct i40e_queue_stats) / sizeof(u64))) |
---|
182 | | -#define I40E_GLOBAL_STATS_LEN ARRAY_SIZE(i40e_gstrings_stats) |
---|
183 | 386 | #define I40E_NETDEV_STATS_LEN ARRAY_SIZE(i40e_gstrings_net_stats) |
---|
| 387 | + |
---|
184 | 388 | #define I40E_MISC_STATS_LEN ARRAY_SIZE(i40e_gstrings_misc_stats) |
---|
185 | | -#define I40E_VSI_STATS_LEN(n) (I40E_NETDEV_STATS_LEN + \ |
---|
186 | | - I40E_MISC_STATS_LEN + \ |
---|
187 | | - I40E_QUEUE_STATS_LEN((n))) |
---|
| 389 | + |
---|
| 390 | +#define I40E_VSI_STATS_LEN (I40E_NETDEV_STATS_LEN + I40E_MISC_STATS_LEN) |
---|
188 | 391 | |
---|
189 | 392 | #define I40E_PFC_STATS_LEN (ARRAY_SIZE(i40e_gstrings_pfc_stats) * \ |
---|
190 | 393 | I40E_MAX_USER_PRIORITY) |
---|
.. | .. |
---|
193 | 396 | (ARRAY_SIZE(i40e_gstrings_veb_tc_stats) * \ |
---|
194 | 397 | I40E_MAX_TRAFFIC_CLASS)) |
---|
195 | 398 | |
---|
196 | | -#define I40E_PF_STATS_LEN(n) (I40E_GLOBAL_STATS_LEN + \ |
---|
| 399 | +#define I40E_GLOBAL_STATS_LEN ARRAY_SIZE(i40e_gstrings_stats) |
---|
| 400 | + |
---|
| 401 | +#define I40E_PF_STATS_LEN (I40E_GLOBAL_STATS_LEN + \ |
---|
197 | 402 | I40E_PFC_STATS_LEN + \ |
---|
198 | 403 | I40E_VEB_STATS_LEN + \ |
---|
199 | | - I40E_VSI_STATS_LEN((n))) |
---|
| 404 | + I40E_VSI_STATS_LEN) |
---|
| 405 | + |
---|
| 406 | +/* Length of stats for a single queue */ |
---|
| 407 | +#define I40E_QUEUE_STATS_LEN ARRAY_SIZE(i40e_gstrings_queue_stats) |
---|
200 | 408 | |
---|
201 | 409 | enum i40e_ethtool_test_id { |
---|
202 | 410 | I40E_ETH_TEST_REG = 0, |
---|
.. | .. |
---|
229 | 437 | static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = { |
---|
230 | 438 | /* NOTE: MFP setting cannot be changed */ |
---|
231 | 439 | I40E_PRIV_FLAG("MFP", I40E_FLAG_MFP_ENABLED, 1), |
---|
| 440 | + I40E_PRIV_FLAG("total-port-shutdown", |
---|
| 441 | + I40E_FLAG_TOTAL_PORT_SHUTDOWN_ENABLED, 1), |
---|
232 | 442 | I40E_PRIV_FLAG("LinkPolling", I40E_FLAG_LINK_POLLING_ENABLED, 0), |
---|
233 | 443 | I40E_PRIV_FLAG("flow-director-atr", I40E_FLAG_FD_ATR_ENABLED, 0), |
---|
234 | 444 | I40E_PRIV_FLAG("veb-stats", I40E_FLAG_VEB_STATS_ENABLED, 0), |
---|
.. | .. |
---|
239 | 449 | I40E_PRIV_FLAG("disable-source-pruning", |
---|
240 | 450 | I40E_FLAG_SOURCE_PRUNING_DISABLED, 0), |
---|
241 | 451 | I40E_PRIV_FLAG("disable-fw-lldp", I40E_FLAG_DISABLE_FW_LLDP, 0), |
---|
| 452 | + I40E_PRIV_FLAG("rs-fec", I40E_FLAG_RS_FEC, 0), |
---|
| 453 | + I40E_PRIV_FLAG("base-r-fec", I40E_FLAG_BASE_R_FEC, 0), |
---|
242 | 454 | }; |
---|
243 | 455 | |
---|
244 | 456 | #define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gstrings_priv_flags) |
---|
.. | .. |
---|
307 | 519 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
308 | 520 | 10000baseT_Full); |
---|
309 | 521 | } |
---|
| 522 | + if (phy_types & I40E_CAP_PHY_TYPE_2_5GBASE_T) { |
---|
| 523 | + ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
| 524 | + 2500baseT_Full); |
---|
| 525 | + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_2_5GB) |
---|
| 526 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 527 | + 2500baseT_Full); |
---|
| 528 | + } |
---|
| 529 | + if (phy_types & I40E_CAP_PHY_TYPE_5GBASE_T) { |
---|
| 530 | + ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
| 531 | + 5000baseT_Full); |
---|
| 532 | + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_5GB) |
---|
| 533 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 534 | + 5000baseT_Full); |
---|
| 535 | + } |
---|
310 | 536 | if (phy_types & I40E_CAP_PHY_TYPE_XLAUI || |
---|
311 | 537 | phy_types & I40E_CAP_PHY_TYPE_XLPPI || |
---|
312 | 538 | phy_types & I40E_CAP_PHY_TYPE_40GBASE_AOC) |
---|
.. | .. |
---|
334 | 560 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
335 | 561 | 1000baseT_Full); |
---|
336 | 562 | } |
---|
337 | | - if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_SR4) |
---|
| 563 | + if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_SR4) { |
---|
338 | 564 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
339 | 565 | 40000baseSR4_Full); |
---|
340 | | - if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_LR4) |
---|
341 | | - ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
342 | | - 40000baseLR4_Full); |
---|
343 | | - if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_KR4) { |
---|
| 566 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 567 | + 40000baseSR4_Full); |
---|
| 568 | + } |
---|
| 569 | + if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_LR4) { |
---|
344 | 570 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
345 | 571 | 40000baseLR4_Full); |
---|
346 | 572 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
347 | 573 | 40000baseLR4_Full); |
---|
| 574 | + } |
---|
| 575 | + if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_KR4) { |
---|
| 576 | + ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
| 577 | + 40000baseKR4_Full); |
---|
| 578 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 579 | + 40000baseKR4_Full); |
---|
348 | 580 | } |
---|
349 | 581 | if (phy_types & I40E_CAP_PHY_TYPE_20GBASE_KR2) { |
---|
350 | 582 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
.. | .. |
---|
407 | 639 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
408 | 640 | 25000baseCR_Full); |
---|
409 | 641 | } |
---|
| 642 | + if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR || |
---|
| 643 | + phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR || |
---|
| 644 | + phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR || |
---|
| 645 | + phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR || |
---|
| 646 | + phy_types & I40E_CAP_PHY_TYPE_25GBASE_AOC || |
---|
| 647 | + phy_types & I40E_CAP_PHY_TYPE_25GBASE_ACC) { |
---|
| 648 | + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); |
---|
| 649 | + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); |
---|
| 650 | + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); |
---|
| 651 | + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB) { |
---|
| 652 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 653 | + FEC_NONE); |
---|
| 654 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 655 | + FEC_RS); |
---|
| 656 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 657 | + FEC_BASER); |
---|
| 658 | + } |
---|
| 659 | + } |
---|
410 | 660 | /* need to add new 10G PHY types */ |
---|
411 | 661 | if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 || |
---|
412 | 662 | phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU) { |
---|
.. | .. |
---|
449 | 699 | phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR || |
---|
450 | 700 | phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR || |
---|
451 | 701 | phy_types & I40E_CAP_PHY_TYPE_20GBASE_KR2 || |
---|
452 | | - phy_types & I40E_CAP_PHY_TYPE_10GBASE_T || |
---|
453 | 702 | phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR || |
---|
454 | 703 | phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR || |
---|
455 | 704 | phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4 || |
---|
456 | 705 | phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR || |
---|
457 | 706 | phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU || |
---|
458 | 707 | phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 || |
---|
| 708 | + phy_types & I40E_CAP_PHY_TYPE_10GBASE_T || |
---|
| 709 | + phy_types & I40E_CAP_PHY_TYPE_5GBASE_T || |
---|
| 710 | + phy_types & I40E_CAP_PHY_TYPE_2_5GBASE_T || |
---|
459 | 711 | phy_types & I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL || |
---|
460 | 712 | phy_types & I40E_CAP_PHY_TYPE_1000BASE_T || |
---|
461 | 713 | phy_types & I40E_CAP_PHY_TYPE_1000BASE_SX || |
---|
.. | .. |
---|
466 | 718 | Autoneg); |
---|
467 | 719 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
468 | 720 | Autoneg); |
---|
| 721 | + } |
---|
| 722 | +} |
---|
| 723 | + |
---|
| 724 | +/** |
---|
| 725 | + * i40e_get_settings_link_up_fec - Get the FEC mode encoding from mask |
---|
| 726 | + * @req_fec_info: mask request FEC info |
---|
| 727 | + * @ks: ethtool ksettings to fill in |
---|
| 728 | + **/ |
---|
| 729 | +static void i40e_get_settings_link_up_fec(u8 req_fec_info, |
---|
| 730 | + struct ethtool_link_ksettings *ks) |
---|
| 731 | +{ |
---|
| 732 | + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); |
---|
| 733 | + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); |
---|
| 734 | + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); |
---|
| 735 | + |
---|
| 736 | + if ((I40E_AQ_SET_FEC_REQUEST_RS & req_fec_info) && |
---|
| 737 | + (I40E_AQ_SET_FEC_REQUEST_KR & req_fec_info)) { |
---|
| 738 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 739 | + FEC_NONE); |
---|
| 740 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 741 | + FEC_BASER); |
---|
| 742 | + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); |
---|
| 743 | + } else if (I40E_AQ_SET_FEC_REQUEST_RS & req_fec_info) { |
---|
| 744 | + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); |
---|
| 745 | + } else if (I40E_AQ_SET_FEC_REQUEST_KR & req_fec_info) { |
---|
| 746 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 747 | + FEC_BASER); |
---|
| 748 | + } else { |
---|
| 749 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 750 | + FEC_NONE); |
---|
469 | 751 | } |
---|
470 | 752 | } |
---|
471 | 753 | |
---|
.. | .. |
---|
501 | 783 | case I40E_PHY_TYPE_40GBASE_AOC: |
---|
502 | 784 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
503 | 785 | 40000baseCR4_Full); |
---|
| 786 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 787 | + 40000baseCR4_Full); |
---|
504 | 788 | break; |
---|
505 | 789 | case I40E_PHY_TYPE_40GBASE_SR4: |
---|
506 | 790 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
507 | 791 | 40000baseSR4_Full); |
---|
| 792 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 793 | + 40000baseSR4_Full); |
---|
508 | 794 | break; |
---|
509 | 795 | case I40E_PHY_TYPE_40GBASE_LR4: |
---|
510 | 796 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
| 797 | + 40000baseLR4_Full); |
---|
| 798 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
511 | 799 | 40000baseLR4_Full); |
---|
512 | 800 | break; |
---|
513 | 801 | case I40E_PHY_TYPE_25GBASE_SR: |
---|
.. | .. |
---|
522 | 810 | 25000baseSR_Full); |
---|
523 | 811 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
524 | 812 | 25000baseSR_Full); |
---|
| 813 | + i40e_get_settings_link_up_fec(hw_link_info->req_fec_info, ks); |
---|
525 | 814 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
526 | 815 | 10000baseSR_Full); |
---|
527 | 816 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
.. | .. |
---|
552 | 841 | 10000baseT_Full); |
---|
553 | 842 | break; |
---|
554 | 843 | case I40E_PHY_TYPE_10GBASE_T: |
---|
| 844 | + case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS: |
---|
| 845 | + case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS: |
---|
555 | 846 | case I40E_PHY_TYPE_1000BASE_T: |
---|
556 | 847 | case I40E_PHY_TYPE_100BASE_TX: |
---|
557 | 848 | ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); |
---|
558 | 849 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
559 | 850 | 10000baseT_Full); |
---|
| 851 | + ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
| 852 | + 5000baseT_Full); |
---|
| 853 | + ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
| 854 | + 2500baseT_Full); |
---|
560 | 855 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
561 | 856 | 1000baseT_Full); |
---|
562 | 857 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
.. | .. |
---|
565 | 860 | if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) |
---|
566 | 861 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
567 | 862 | 10000baseT_Full); |
---|
| 863 | + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_5GB) |
---|
| 864 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 865 | + 5000baseT_Full); |
---|
| 866 | + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_2_5GB) |
---|
| 867 | + ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
| 868 | + 2500baseT_Full); |
---|
568 | 869 | if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) |
---|
569 | 870 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
570 | 871 | 1000baseT_Full); |
---|
.. | .. |
---|
599 | 900 | if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) |
---|
600 | 901 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
601 | 902 | 10000baseT_Full); |
---|
| 903 | + i40e_get_settings_link_up_fec(hw_link_info->req_fec_info, ks); |
---|
602 | 904 | break; |
---|
603 | 905 | case I40E_PHY_TYPE_SGMII: |
---|
604 | 906 | ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); |
---|
.. | .. |
---|
639 | 941 | 40000baseKR4_Full); |
---|
640 | 942 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
641 | 943 | 25000baseKR_Full); |
---|
| 944 | + i40e_get_settings_link_up_fec(hw_link_info->req_fec_info, ks); |
---|
642 | 945 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
643 | 946 | 20000baseKR2_Full); |
---|
644 | 947 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
.. | .. |
---|
656 | 959 | 25000baseCR_Full); |
---|
657 | 960 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
658 | 961 | 25000baseCR_Full); |
---|
| 962 | + i40e_get_settings_link_up_fec(hw_link_info->req_fec_info, ks); |
---|
| 963 | + |
---|
659 | 964 | break; |
---|
660 | 965 | case I40E_PHY_TYPE_25GBASE_AOC: |
---|
661 | 966 | case I40E_PHY_TYPE_25GBASE_ACC: |
---|
.. | .. |
---|
663 | 968 | ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); |
---|
664 | 969 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
665 | 970 | 25000baseCR_Full); |
---|
666 | | - |
---|
667 | 971 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
668 | 972 | 25000baseCR_Full); |
---|
| 973 | + i40e_get_settings_link_up_fec(hw_link_info->req_fec_info, ks); |
---|
| 974 | + |
---|
669 | 975 | ethtool_link_ksettings_add_link_mode(ks, supported, |
---|
670 | 976 | 10000baseCR_Full); |
---|
671 | 977 | ethtool_link_ksettings_add_link_mode(ks, advertising, |
---|
.. | .. |
---|
700 | 1006 | case I40E_LINK_SPEED_10GB: |
---|
701 | 1007 | ks->base.speed = SPEED_10000; |
---|
702 | 1008 | break; |
---|
| 1009 | + case I40E_LINK_SPEED_5GB: |
---|
| 1010 | + ks->base.speed = SPEED_5000; |
---|
| 1011 | + break; |
---|
| 1012 | + case I40E_LINK_SPEED_2_5GB: |
---|
| 1013 | + ks->base.speed = SPEED_2500; |
---|
| 1014 | + break; |
---|
703 | 1015 | case I40E_LINK_SPEED_1GB: |
---|
704 | 1016 | ks->base.speed = SPEED_1000; |
---|
705 | 1017 | break; |
---|
.. | .. |
---|
707 | 1019 | ks->base.speed = SPEED_100; |
---|
708 | 1020 | break; |
---|
709 | 1021 | default: |
---|
| 1022 | + ks->base.speed = SPEED_UNKNOWN; |
---|
710 | 1023 | break; |
---|
711 | 1024 | } |
---|
712 | 1025 | ks->base.duplex = DUPLEX_FULL; |
---|
.. | .. |
---|
786 | 1099 | break; |
---|
787 | 1100 | case I40E_MEDIA_TYPE_FIBER: |
---|
788 | 1101 | ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); |
---|
| 1102 | + ethtool_link_ksettings_add_link_mode(ks, advertising, FIBRE); |
---|
789 | 1103 | ks->base.port = PORT_FIBRE; |
---|
790 | 1104 | break; |
---|
791 | 1105 | case I40E_MEDIA_TYPE_UNKNOWN: |
---|
.. | .. |
---|
984 | 1298 | 10000baseLR_Full)) |
---|
985 | 1299 | config.link_speed |= I40E_LINK_SPEED_10GB; |
---|
986 | 1300 | if (ethtool_link_ksettings_test_link_mode(ks, advertising, |
---|
| 1301 | + 2500baseT_Full)) |
---|
| 1302 | + config.link_speed |= I40E_LINK_SPEED_2_5GB; |
---|
| 1303 | + if (ethtool_link_ksettings_test_link_mode(ks, advertising, |
---|
| 1304 | + 5000baseT_Full)) |
---|
| 1305 | + config.link_speed |= I40E_LINK_SPEED_5GB; |
---|
| 1306 | + if (ethtool_link_ksettings_test_link_mode(ks, advertising, |
---|
987 | 1307 | 20000baseKR2_Full)) |
---|
988 | 1308 | config.link_speed |= I40E_LINK_SPEED_20GB; |
---|
989 | 1309 | if (ethtool_link_ksettings_test_link_mode(ks, advertising, |
---|
.. | .. |
---|
1059 | 1379 | clear_bit(__I40E_CONFIG_BUSY, pf->state); |
---|
1060 | 1380 | |
---|
1061 | 1381 | return err; |
---|
| 1382 | +} |
---|
| 1383 | + |
---|
| 1384 | +static int i40e_set_fec_cfg(struct net_device *netdev, u8 fec_cfg) |
---|
| 1385 | +{ |
---|
| 1386 | + struct i40e_netdev_priv *np = netdev_priv(netdev); |
---|
| 1387 | + struct i40e_aq_get_phy_abilities_resp abilities; |
---|
| 1388 | + struct i40e_pf *pf = np->vsi->back; |
---|
| 1389 | + struct i40e_hw *hw = &pf->hw; |
---|
| 1390 | + i40e_status status = 0; |
---|
| 1391 | + u32 flags = 0; |
---|
| 1392 | + int err = 0; |
---|
| 1393 | + |
---|
| 1394 | + flags = READ_ONCE(pf->flags); |
---|
| 1395 | + i40e_set_fec_in_flags(fec_cfg, &flags); |
---|
| 1396 | + |
---|
| 1397 | + /* Get the current phy config */ |
---|
| 1398 | + memset(&abilities, 0, sizeof(abilities)); |
---|
| 1399 | + status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, |
---|
| 1400 | + NULL); |
---|
| 1401 | + if (status) { |
---|
| 1402 | + err = -EAGAIN; |
---|
| 1403 | + goto done; |
---|
| 1404 | + } |
---|
| 1405 | + |
---|
| 1406 | + if (abilities.fec_cfg_curr_mod_ext_info != fec_cfg) { |
---|
| 1407 | + struct i40e_aq_set_phy_config config; |
---|
| 1408 | + |
---|
| 1409 | + memset(&config, 0, sizeof(config)); |
---|
| 1410 | + config.phy_type = abilities.phy_type; |
---|
| 1411 | + config.abilities = abilities.abilities | |
---|
| 1412 | + I40E_AQ_PHY_ENABLE_ATOMIC_LINK; |
---|
| 1413 | + config.phy_type_ext = abilities.phy_type_ext; |
---|
| 1414 | + config.link_speed = abilities.link_speed; |
---|
| 1415 | + config.eee_capability = abilities.eee_capability; |
---|
| 1416 | + config.eeer = abilities.eeer_val; |
---|
| 1417 | + config.low_power_ctrl = abilities.d3_lpan; |
---|
| 1418 | + config.fec_config = fec_cfg & I40E_AQ_PHY_FEC_CONFIG_MASK; |
---|
| 1419 | + status = i40e_aq_set_phy_config(hw, &config, NULL); |
---|
| 1420 | + if (status) { |
---|
| 1421 | + netdev_info(netdev, |
---|
| 1422 | + "Set phy config failed, err %s aq_err %s\n", |
---|
| 1423 | + i40e_stat_str(hw, status), |
---|
| 1424 | + i40e_aq_str(hw, hw->aq.asq_last_status)); |
---|
| 1425 | + err = -EAGAIN; |
---|
| 1426 | + goto done; |
---|
| 1427 | + } |
---|
| 1428 | + pf->flags = flags; |
---|
| 1429 | + status = i40e_update_link_info(hw); |
---|
| 1430 | + if (status) |
---|
| 1431 | + /* debug level message only due to relation to the link |
---|
| 1432 | + * itself rather than to the FEC settings |
---|
| 1433 | + * (e.g. no physical connection etc.) |
---|
| 1434 | + */ |
---|
| 1435 | + netdev_dbg(netdev, |
---|
| 1436 | + "Updating link info failed with err %s aq_err %s\n", |
---|
| 1437 | + i40e_stat_str(hw, status), |
---|
| 1438 | + i40e_aq_str(hw, hw->aq.asq_last_status)); |
---|
| 1439 | + } |
---|
| 1440 | + |
---|
| 1441 | +done: |
---|
| 1442 | + return err; |
---|
| 1443 | +} |
---|
| 1444 | + |
---|
| 1445 | +static int i40e_get_fec_param(struct net_device *netdev, |
---|
| 1446 | + struct ethtool_fecparam *fecparam) |
---|
| 1447 | +{ |
---|
| 1448 | + struct i40e_netdev_priv *np = netdev_priv(netdev); |
---|
| 1449 | + struct i40e_aq_get_phy_abilities_resp abilities; |
---|
| 1450 | + struct i40e_pf *pf = np->vsi->back; |
---|
| 1451 | + struct i40e_hw *hw = &pf->hw; |
---|
| 1452 | + i40e_status status = 0; |
---|
| 1453 | + int err = 0; |
---|
| 1454 | + u8 fec_cfg; |
---|
| 1455 | + |
---|
| 1456 | + /* Get the current phy config */ |
---|
| 1457 | + memset(&abilities, 0, sizeof(abilities)); |
---|
| 1458 | + status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, |
---|
| 1459 | + NULL); |
---|
| 1460 | + if (status) { |
---|
| 1461 | + err = -EAGAIN; |
---|
| 1462 | + goto done; |
---|
| 1463 | + } |
---|
| 1464 | + |
---|
| 1465 | + fecparam->fec = 0; |
---|
| 1466 | + fec_cfg = abilities.fec_cfg_curr_mod_ext_info; |
---|
| 1467 | + if (fec_cfg & I40E_AQ_SET_FEC_AUTO) |
---|
| 1468 | + fecparam->fec |= ETHTOOL_FEC_AUTO; |
---|
| 1469 | + else if (fec_cfg & (I40E_AQ_SET_FEC_REQUEST_RS | |
---|
| 1470 | + I40E_AQ_SET_FEC_ABILITY_RS)) |
---|
| 1471 | + fecparam->fec |= ETHTOOL_FEC_RS; |
---|
| 1472 | + else if (fec_cfg & (I40E_AQ_SET_FEC_REQUEST_KR | |
---|
| 1473 | + I40E_AQ_SET_FEC_ABILITY_KR)) |
---|
| 1474 | + fecparam->fec |= ETHTOOL_FEC_BASER; |
---|
| 1475 | + if (fec_cfg == 0) |
---|
| 1476 | + fecparam->fec |= ETHTOOL_FEC_OFF; |
---|
| 1477 | + |
---|
| 1478 | + if (hw->phy.link_info.fec_info & I40E_AQ_CONFIG_FEC_KR_ENA) |
---|
| 1479 | + fecparam->active_fec = ETHTOOL_FEC_BASER; |
---|
| 1480 | + else if (hw->phy.link_info.fec_info & I40E_AQ_CONFIG_FEC_RS_ENA) |
---|
| 1481 | + fecparam->active_fec = ETHTOOL_FEC_RS; |
---|
| 1482 | + else |
---|
| 1483 | + fecparam->active_fec = ETHTOOL_FEC_OFF; |
---|
| 1484 | +done: |
---|
| 1485 | + return err; |
---|
| 1486 | +} |
---|
| 1487 | + |
---|
| 1488 | +static int i40e_set_fec_param(struct net_device *netdev, |
---|
| 1489 | + struct ethtool_fecparam *fecparam) |
---|
| 1490 | +{ |
---|
| 1491 | + struct i40e_netdev_priv *np = netdev_priv(netdev); |
---|
| 1492 | + struct i40e_pf *pf = np->vsi->back; |
---|
| 1493 | + struct i40e_hw *hw = &pf->hw; |
---|
| 1494 | + u8 fec_cfg = 0; |
---|
| 1495 | + |
---|
| 1496 | + if (hw->device_id != I40E_DEV_ID_25G_SFP28 && |
---|
| 1497 | + hw->device_id != I40E_DEV_ID_25G_B && |
---|
| 1498 | + hw->device_id != I40E_DEV_ID_KX_X722) |
---|
| 1499 | + return -EPERM; |
---|
| 1500 | + |
---|
| 1501 | + if (hw->mac.type == I40E_MAC_X722 && |
---|
| 1502 | + !(hw->flags & I40E_HW_FLAG_X722_FEC_REQUEST_CAPABLE)) { |
---|
| 1503 | + netdev_err(netdev, "Setting FEC encoding not supported by firmware. Please update the NVM image.\n"); |
---|
| 1504 | + return -EOPNOTSUPP; |
---|
| 1505 | + } |
---|
| 1506 | + |
---|
| 1507 | + switch (fecparam->fec) { |
---|
| 1508 | + case ETHTOOL_FEC_AUTO: |
---|
| 1509 | + fec_cfg = I40E_AQ_SET_FEC_AUTO; |
---|
| 1510 | + break; |
---|
| 1511 | + case ETHTOOL_FEC_RS: |
---|
| 1512 | + fec_cfg = (I40E_AQ_SET_FEC_REQUEST_RS | |
---|
| 1513 | + I40E_AQ_SET_FEC_ABILITY_RS); |
---|
| 1514 | + break; |
---|
| 1515 | + case ETHTOOL_FEC_BASER: |
---|
| 1516 | + fec_cfg = (I40E_AQ_SET_FEC_REQUEST_KR | |
---|
| 1517 | + I40E_AQ_SET_FEC_ABILITY_KR); |
---|
| 1518 | + break; |
---|
| 1519 | + case ETHTOOL_FEC_OFF: |
---|
| 1520 | + case ETHTOOL_FEC_NONE: |
---|
| 1521 | + fec_cfg = 0; |
---|
| 1522 | + break; |
---|
| 1523 | + default: |
---|
| 1524 | + dev_warn(&pf->pdev->dev, "Unsupported FEC mode: %d", |
---|
| 1525 | + fecparam->fec); |
---|
| 1526 | + return -EINVAL; |
---|
| 1527 | + } |
---|
| 1528 | + |
---|
| 1529 | + return i40e_set_fec_cfg(netdev, fec_cfg); |
---|
1062 | 1530 | } |
---|
1063 | 1531 | |
---|
1064 | 1532 | static int i40e_nway_reset(struct net_device *netdev) |
---|
.. | .. |
---|
1176 | 1644 | else if (!pause->rx_pause && !pause->tx_pause) |
---|
1177 | 1645 | hw->fc.requested_mode = I40E_FC_NONE; |
---|
1178 | 1646 | else |
---|
1179 | | - return -EINVAL; |
---|
| 1647 | + return -EINVAL; |
---|
1180 | 1648 | |
---|
1181 | 1649 | /* Tell the OS link is going down, the link will go back up when fw |
---|
1182 | 1650 | * says it is ready asynchronously |
---|
.. | .. |
---|
1438 | 1906 | struct i40e_pf *pf = vsi->back; |
---|
1439 | 1907 | |
---|
1440 | 1908 | strlcpy(drvinfo->driver, i40e_driver_name, sizeof(drvinfo->driver)); |
---|
1441 | | - strlcpy(drvinfo->version, i40e_driver_version_str, |
---|
1442 | | - sizeof(drvinfo->version)); |
---|
1443 | 1909 | strlcpy(drvinfo->fw_version, i40e_nvm_version_str(&pf->hw), |
---|
1444 | 1910 | sizeof(drvinfo->fw_version)); |
---|
1445 | 1911 | strlcpy(drvinfo->bus_info, pci_name(pf->pdev), |
---|
.. | .. |
---|
1512 | 1978 | (new_rx_count == vsi->rx_rings[0]->count)) |
---|
1513 | 1979 | return 0; |
---|
1514 | 1980 | |
---|
| 1981 | + /* If there is a AF_XDP page pool attached to any of Rx rings, |
---|
| 1982 | + * disallow changing the number of descriptors -- regardless |
---|
| 1983 | + * if the netdev is running or not. |
---|
| 1984 | + */ |
---|
| 1985 | + if (i40e_xsk_any_rx_ring_enabled(vsi)) |
---|
| 1986 | + return -EBUSY; |
---|
| 1987 | + |
---|
1515 | 1988 | while (test_and_set_bit(__I40E_CONFIG_BUSY, pf->state)) { |
---|
1516 | 1989 | timeout--; |
---|
1517 | 1990 | if (!timeout) |
---|
.. | .. |
---|
1527 | 2000 | if (i40e_enabled_xdp_vsi(vsi)) |
---|
1528 | 2001 | vsi->xdp_rings[i]->count = new_tx_count; |
---|
1529 | 2002 | } |
---|
| 2003 | + vsi->num_tx_desc = new_tx_count; |
---|
| 2004 | + vsi->num_rx_desc = new_rx_count; |
---|
1530 | 2005 | goto done; |
---|
1531 | 2006 | } |
---|
1532 | 2007 | |
---|
.. | .. |
---|
1663 | 2138 | rx_rings = NULL; |
---|
1664 | 2139 | } |
---|
1665 | 2140 | |
---|
| 2141 | + vsi->num_tx_desc = new_tx_count; |
---|
| 2142 | + vsi->num_rx_desc = new_rx_count; |
---|
1666 | 2143 | i40e_up(vsi); |
---|
1667 | 2144 | |
---|
1668 | 2145 | free_tx: |
---|
.. | .. |
---|
1701 | 2178 | struct i40e_netdev_priv *np = netdev_priv(netdev); |
---|
1702 | 2179 | struct i40e_vsi *vsi = np->vsi; |
---|
1703 | 2180 | struct i40e_pf *pf = vsi->back; |
---|
| 2181 | + int stats_len; |
---|
1704 | 2182 | |
---|
1705 | 2183 | if (vsi == pf->vsi[pf->lan_vsi] && pf->hw.partition_id == 1) |
---|
1706 | | - return I40E_PF_STATS_LEN(netdev); |
---|
| 2184 | + stats_len = I40E_PF_STATS_LEN; |
---|
1707 | 2185 | else |
---|
1708 | | - return I40E_VSI_STATS_LEN(netdev); |
---|
| 2186 | + stats_len = I40E_VSI_STATS_LEN; |
---|
| 2187 | + |
---|
| 2188 | + /* The number of stats reported for a given net_device must remain |
---|
| 2189 | + * constant throughout the life of that device. |
---|
| 2190 | + * |
---|
| 2191 | + * This is because the API for obtaining the size, strings, and stats |
---|
| 2192 | + * is spread out over three separate ethtool ioctls. There is no safe |
---|
| 2193 | + * way to lock the number of stats across these calls, so we must |
---|
| 2194 | + * assume that they will never change. |
---|
| 2195 | + * |
---|
| 2196 | + * Due to this, we report the maximum number of queues, even if not |
---|
| 2197 | + * every queue is currently configured. Since we always allocate |
---|
| 2198 | + * queues in pairs, we'll just use netdev->num_tx_queues * 2. This |
---|
| 2199 | + * works because the num_tx_queues is set at device creation and never |
---|
| 2200 | + * changes. |
---|
| 2201 | + */ |
---|
| 2202 | + stats_len += I40E_QUEUE_STATS_LEN * 2 * netdev->num_tx_queues; |
---|
| 2203 | + |
---|
| 2204 | + return stats_len; |
---|
1709 | 2205 | } |
---|
1710 | 2206 | |
---|
1711 | 2207 | static int i40e_get_sset_count(struct net_device *netdev, int sset) |
---|
.. | .. |
---|
1728 | 2224 | } |
---|
1729 | 2225 | |
---|
1730 | 2226 | /** |
---|
1731 | | - * i40e_add_one_ethtool_stat - copy the stat into the supplied buffer |
---|
1732 | | - * @data: location to store the stat value |
---|
1733 | | - * @pointer: basis for where to copy from |
---|
1734 | | - * @stat: the stat definition |
---|
| 2227 | + * i40e_get_veb_tc_stats - copy VEB TC statistics to formatted structure |
---|
| 2228 | + * @tc: the TC statistics in VEB structure (veb->tc_stats) |
---|
| 2229 | + * @i: the index of traffic class in (veb->tc_stats) structure to copy |
---|
1735 | 2230 | * |
---|
1736 | | - * Copies the stat data defined by the pointer and stat structure pair into |
---|
1737 | | - * the memory supplied as data. Used to implement i40e_add_ethtool_stats. |
---|
1738 | | - * If the pointer is null, data will be zero'd. |
---|
1739 | | - */ |
---|
1740 | | -static inline void |
---|
1741 | | -i40e_add_one_ethtool_stat(u64 *data, void *pointer, |
---|
1742 | | - const struct i40e_stats *stat) |
---|
1743 | | -{ |
---|
1744 | | - char *p; |
---|
1745 | | - |
---|
1746 | | - if (!pointer) { |
---|
1747 | | - /* ensure that the ethtool data buffer is zero'd for any stats |
---|
1748 | | - * which don't have a valid pointer. |
---|
1749 | | - */ |
---|
1750 | | - *data = 0; |
---|
1751 | | - return; |
---|
1752 | | - } |
---|
1753 | | - |
---|
1754 | | - p = (char *)pointer + stat->stat_offset; |
---|
1755 | | - switch (stat->sizeof_stat) { |
---|
1756 | | - case sizeof(u64): |
---|
1757 | | - *data = *((u64 *)p); |
---|
1758 | | - break; |
---|
1759 | | - case sizeof(u32): |
---|
1760 | | - *data = *((u32 *)p); |
---|
1761 | | - break; |
---|
1762 | | - case sizeof(u16): |
---|
1763 | | - *data = *((u16 *)p); |
---|
1764 | | - break; |
---|
1765 | | - case sizeof(u8): |
---|
1766 | | - *data = *((u8 *)p); |
---|
1767 | | - break; |
---|
1768 | | - default: |
---|
1769 | | - WARN_ONCE(1, "unexpected stat size for %s", |
---|
1770 | | - stat->stat_string); |
---|
1771 | | - *data = 0; |
---|
1772 | | - } |
---|
1773 | | -} |
---|
1774 | | - |
---|
1775 | | -/** |
---|
1776 | | - * __i40e_add_ethtool_stats - copy stats into the ethtool supplied buffer |
---|
1777 | | - * @data: ethtool stats buffer |
---|
1778 | | - * @pointer: location to copy stats from |
---|
1779 | | - * @stats: array of stats to copy |
---|
1780 | | - * @size: the size of the stats definition |
---|
1781 | | - * |
---|
1782 | | - * Copy the stats defined by the stats array using the pointer as a base into |
---|
1783 | | - * the data buffer supplied by ethtool. Updates the data pointer to point to |
---|
1784 | | - * the next empty location for successive calls to __i40e_add_ethtool_stats. |
---|
1785 | | - * If pointer is null, set the data values to zero and update the pointer to |
---|
1786 | | - * skip these stats. |
---|
| 2231 | + * Copy VEB TC statistics from structure of arrays (veb->tc_stats) to |
---|
| 2232 | + * one dimensional structure i40e_cp_veb_tc_stats. |
---|
| 2233 | + * Produce formatted i40e_cp_veb_tc_stats structure of the VEB TC |
---|
| 2234 | + * statistics for the given TC. |
---|
1787 | 2235 | **/ |
---|
1788 | | -static inline void |
---|
1789 | | -__i40e_add_ethtool_stats(u64 **data, void *pointer, |
---|
1790 | | - const struct i40e_stats stats[], |
---|
1791 | | - const unsigned int size) |
---|
| 2236 | +static struct i40e_cp_veb_tc_stats |
---|
| 2237 | +i40e_get_veb_tc_stats(struct i40e_veb_tc_stats *tc, unsigned int i) |
---|
1792 | 2238 | { |
---|
1793 | | - unsigned int i; |
---|
| 2239 | + struct i40e_cp_veb_tc_stats veb_tc = { |
---|
| 2240 | + .tc_rx_packets = tc->tc_rx_packets[i], |
---|
| 2241 | + .tc_rx_bytes = tc->tc_rx_bytes[i], |
---|
| 2242 | + .tc_tx_packets = tc->tc_tx_packets[i], |
---|
| 2243 | + .tc_tx_bytes = tc->tc_tx_bytes[i], |
---|
| 2244 | + }; |
---|
1794 | 2245 | |
---|
1795 | | - for (i = 0; i < size; i++) |
---|
1796 | | - i40e_add_one_ethtool_stat((*data)++, pointer, &stats[i]); |
---|
| 2246 | + return veb_tc; |
---|
1797 | 2247 | } |
---|
1798 | | - |
---|
1799 | | -/** |
---|
1800 | | - * i40e_add_ethtool_stats - copy stats into ethtool supplied buffer |
---|
1801 | | - * @data: ethtool stats buffer |
---|
1802 | | - * @pointer: location where stats are stored |
---|
1803 | | - * @stats: static const array of stat definitions |
---|
1804 | | - * |
---|
1805 | | - * Macro to ease the use of __i40e_add_ethtool_stats by taking a static |
---|
1806 | | - * constant stats array and passing the ARRAY_SIZE(). This avoids typos by |
---|
1807 | | - * ensuring that we pass the size associated with the given stats array. |
---|
1808 | | - * Assumes that stats is an array. |
---|
1809 | | - **/ |
---|
1810 | | -#define i40e_add_ethtool_stats(data, pointer, stats) \ |
---|
1811 | | - __i40e_add_ethtool_stats(data, pointer, stats, ARRAY_SIZE(stats)) |
---|
1812 | 2248 | |
---|
1813 | 2249 | /** |
---|
1814 | 2250 | * i40e_get_pfc_stats - copy HW PFC statistics to formatted structure |
---|
.. | .. |
---|
1853 | 2289 | struct ethtool_stats *stats, u64 *data) |
---|
1854 | 2290 | { |
---|
1855 | 2291 | struct i40e_netdev_priv *np = netdev_priv(netdev); |
---|
1856 | | - struct i40e_ring *tx_ring, *rx_ring; |
---|
1857 | 2292 | struct i40e_vsi *vsi = np->vsi; |
---|
1858 | 2293 | struct i40e_pf *pf = vsi->back; |
---|
1859 | | - struct i40e_veb *veb = pf->veb[pf->lan_veb]; |
---|
| 2294 | + struct i40e_veb *veb = NULL; |
---|
1860 | 2295 | unsigned int i; |
---|
1861 | | - unsigned int start; |
---|
1862 | 2296 | bool veb_stats; |
---|
1863 | 2297 | u64 *p = data; |
---|
1864 | 2298 | |
---|
.. | .. |
---|
1870 | 2304 | i40e_add_ethtool_stats(&data, vsi, i40e_gstrings_misc_stats); |
---|
1871 | 2305 | |
---|
1872 | 2306 | rcu_read_lock(); |
---|
1873 | | - for (i = 0; i < I40E_MAX_NUM_QUEUES(netdev) ; i++) { |
---|
1874 | | - tx_ring = READ_ONCE(vsi->tx_rings[i]); |
---|
1875 | | - |
---|
1876 | | - if (!tx_ring) { |
---|
1877 | | - /* Bump the stat counter to skip these stats, and make |
---|
1878 | | - * sure the memory is zero'd |
---|
1879 | | - */ |
---|
1880 | | - *(data++) = 0; |
---|
1881 | | - *(data++) = 0; |
---|
1882 | | - *(data++) = 0; |
---|
1883 | | - *(data++) = 0; |
---|
1884 | | - continue; |
---|
1885 | | - } |
---|
1886 | | - |
---|
1887 | | - /* process Tx ring statistics */ |
---|
1888 | | - do { |
---|
1889 | | - start = u64_stats_fetch_begin_irq(&tx_ring->syncp); |
---|
1890 | | - data[0] = tx_ring->stats.packets; |
---|
1891 | | - data[1] = tx_ring->stats.bytes; |
---|
1892 | | - } while (u64_stats_fetch_retry_irq(&tx_ring->syncp, start)); |
---|
1893 | | - data += 2; |
---|
1894 | | - |
---|
1895 | | - /* Rx ring is the 2nd half of the queue pair */ |
---|
1896 | | - rx_ring = &tx_ring[1]; |
---|
1897 | | - do { |
---|
1898 | | - start = u64_stats_fetch_begin_irq(&rx_ring->syncp); |
---|
1899 | | - data[0] = rx_ring->stats.packets; |
---|
1900 | | - data[1] = rx_ring->stats.bytes; |
---|
1901 | | - } while (u64_stats_fetch_retry_irq(&rx_ring->syncp, start)); |
---|
1902 | | - data += 2; |
---|
| 2307 | + for (i = 0; i < netdev->num_tx_queues; i++) { |
---|
| 2308 | + i40e_add_queue_stats(&data, READ_ONCE(vsi->tx_rings[i])); |
---|
| 2309 | + i40e_add_queue_stats(&data, READ_ONCE(vsi->rx_rings[i])); |
---|
1903 | 2310 | } |
---|
1904 | 2311 | rcu_read_unlock(); |
---|
| 2312 | + |
---|
1905 | 2313 | if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1) |
---|
1906 | 2314 | goto check_data_pointer; |
---|
1907 | 2315 | |
---|
1908 | 2316 | veb_stats = ((pf->lan_veb != I40E_NO_VEB) && |
---|
| 2317 | + (pf->lan_veb < I40E_MAX_VEB) && |
---|
1909 | 2318 | (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)); |
---|
| 2319 | + |
---|
| 2320 | + if (veb_stats) { |
---|
| 2321 | + veb = pf->veb[pf->lan_veb]; |
---|
| 2322 | + i40e_update_veb_stats(veb); |
---|
| 2323 | + } |
---|
1910 | 2324 | |
---|
1911 | 2325 | /* If veb stats aren't enabled, pass NULL instead of the veb so that |
---|
1912 | 2326 | * we initialize stats to zero and update the data pointer |
---|
.. | .. |
---|
1916 | 2330 | i40e_gstrings_veb_stats); |
---|
1917 | 2331 | |
---|
1918 | 2332 | for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) |
---|
1919 | | - i40e_add_ethtool_stats(&data, veb_stats ? veb : NULL, |
---|
1920 | | - i40e_gstrings_veb_tc_stats); |
---|
| 2333 | + if (veb_stats) { |
---|
| 2334 | + struct i40e_cp_veb_tc_stats veb_tc = |
---|
| 2335 | + i40e_get_veb_tc_stats(&veb->tc_stats, i); |
---|
| 2336 | + |
---|
| 2337 | + i40e_add_ethtool_stats(&data, &veb_tc, |
---|
| 2338 | + i40e_gstrings_veb_tc_stats); |
---|
| 2339 | + } else { |
---|
| 2340 | + i40e_add_ethtool_stats(&data, NULL, |
---|
| 2341 | + i40e_gstrings_veb_tc_stats); |
---|
| 2342 | + } |
---|
1921 | 2343 | |
---|
1922 | 2344 | i40e_add_ethtool_stats(&data, pf, i40e_gstrings_stats); |
---|
1923 | 2345 | |
---|
.. | .. |
---|
1931 | 2353 | WARN_ONCE(data - p != i40e_get_stats_count(netdev), |
---|
1932 | 2354 | "ethtool stats count mismatch!"); |
---|
1933 | 2355 | } |
---|
1934 | | - |
---|
1935 | | -/** |
---|
1936 | | - * __i40e_add_stat_strings - copy stat strings into ethtool buffer |
---|
1937 | | - * @p: ethtool supplied buffer |
---|
1938 | | - * @stats: stat definitions array |
---|
1939 | | - * @size: size of the stats array |
---|
1940 | | - * |
---|
1941 | | - * Format and copy the strings described by stats into the buffer pointed at |
---|
1942 | | - * by p. |
---|
1943 | | - **/ |
---|
1944 | | -static void __i40e_add_stat_strings(u8 **p, const struct i40e_stats stats[], |
---|
1945 | | - const unsigned int size, ...) |
---|
1946 | | -{ |
---|
1947 | | - unsigned int i; |
---|
1948 | | - |
---|
1949 | | - for (i = 0; i < size; i++) { |
---|
1950 | | - va_list args; |
---|
1951 | | - |
---|
1952 | | - va_start(args, size); |
---|
1953 | | - vsnprintf(*p, ETH_GSTRING_LEN, stats[i].stat_string, args); |
---|
1954 | | - *p += ETH_GSTRING_LEN; |
---|
1955 | | - va_end(args); |
---|
1956 | | - } |
---|
1957 | | -} |
---|
1958 | | - |
---|
1959 | | -/** |
---|
1960 | | - * 40e_add_stat_strings - copy stat strings into ethtool buffer |
---|
1961 | | - * @p: ethtool supplied buffer |
---|
1962 | | - * @stats: stat definitions array |
---|
1963 | | - * |
---|
1964 | | - * Format and copy the strings described by the const static stats value into |
---|
1965 | | - * the buffer pointed at by p. Assumes that stats can have ARRAY_SIZE called |
---|
1966 | | - * for it. |
---|
1967 | | - **/ |
---|
1968 | | -#define i40e_add_stat_strings(p, stats, ...) \ |
---|
1969 | | - __i40e_add_stat_strings(p, stats, ARRAY_SIZE(stats), ## __VA_ARGS__) |
---|
1970 | 2356 | |
---|
1971 | 2357 | /** |
---|
1972 | 2358 | * i40e_get_stat_strings - copy stat strings into supplied buffer |
---|
.. | .. |
---|
1990 | 2376 | |
---|
1991 | 2377 | i40e_add_stat_strings(&data, i40e_gstrings_misc_stats); |
---|
1992 | 2378 | |
---|
1993 | | - for (i = 0; i < I40E_MAX_NUM_QUEUES(netdev); i++) { |
---|
1994 | | - snprintf(data, ETH_GSTRING_LEN, "tx-%u.tx_packets", i); |
---|
1995 | | - data += ETH_GSTRING_LEN; |
---|
1996 | | - snprintf(data, ETH_GSTRING_LEN, "tx-%u.tx_bytes", i); |
---|
1997 | | - data += ETH_GSTRING_LEN; |
---|
1998 | | - snprintf(data, ETH_GSTRING_LEN, "rx-%u.rx_packets", i); |
---|
1999 | | - data += ETH_GSTRING_LEN; |
---|
2000 | | - snprintf(data, ETH_GSTRING_LEN, "rx-%u.rx_bytes", i); |
---|
2001 | | - data += ETH_GSTRING_LEN; |
---|
| 2379 | + for (i = 0; i < netdev->num_tx_queues; i++) { |
---|
| 2380 | + i40e_add_stat_strings(&data, i40e_gstrings_queue_stats, |
---|
| 2381 | + "tx", i); |
---|
| 2382 | + i40e_add_stat_strings(&data, i40e_gstrings_queue_stats, |
---|
| 2383 | + "rx", i); |
---|
2002 | 2384 | } |
---|
| 2385 | + |
---|
2003 | 2386 | if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1) |
---|
2004 | | - return; |
---|
| 2387 | + goto check_data_pointer; |
---|
2005 | 2388 | |
---|
2006 | 2389 | i40e_add_stat_strings(&data, i40e_gstrings_veb_stats); |
---|
2007 | 2390 | |
---|
.. | .. |
---|
2013 | 2396 | for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) |
---|
2014 | 2397 | i40e_add_stat_strings(&data, i40e_gstrings_pfc_stats, i); |
---|
2015 | 2398 | |
---|
| 2399 | +check_data_pointer: |
---|
2016 | 2400 | WARN_ONCE(data - p != i40e_get_stats_count(netdev) * ETH_GSTRING_LEN, |
---|
2017 | 2401 | "stat strings count mismatch!"); |
---|
2018 | 2402 | } |
---|
.. | .. |
---|
2099 | 2483 | return 0; |
---|
2100 | 2484 | } |
---|
2101 | 2485 | |
---|
2102 | | -static int i40e_link_test(struct net_device *netdev, u64 *data) |
---|
| 2486 | +static u64 i40e_link_test(struct net_device *netdev, u64 *data) |
---|
2103 | 2487 | { |
---|
2104 | 2488 | struct i40e_netdev_priv *np = netdev_priv(netdev); |
---|
2105 | 2489 | struct i40e_pf *pf = np->vsi->back; |
---|
.. | .. |
---|
2122 | 2506 | return *data; |
---|
2123 | 2507 | } |
---|
2124 | 2508 | |
---|
2125 | | -static int i40e_reg_test(struct net_device *netdev, u64 *data) |
---|
| 2509 | +static u64 i40e_reg_test(struct net_device *netdev, u64 *data) |
---|
2126 | 2510 | { |
---|
2127 | 2511 | struct i40e_netdev_priv *np = netdev_priv(netdev); |
---|
2128 | 2512 | struct i40e_pf *pf = np->vsi->back; |
---|
.. | .. |
---|
2133 | 2517 | return *data; |
---|
2134 | 2518 | } |
---|
2135 | 2519 | |
---|
2136 | | -static int i40e_eeprom_test(struct net_device *netdev, u64 *data) |
---|
| 2520 | +static u64 i40e_eeprom_test(struct net_device *netdev, u64 *data) |
---|
2137 | 2521 | { |
---|
2138 | 2522 | struct i40e_netdev_priv *np = netdev_priv(netdev); |
---|
2139 | 2523 | struct i40e_pf *pf = np->vsi->back; |
---|
.. | .. |
---|
2147 | 2531 | return *data; |
---|
2148 | 2532 | } |
---|
2149 | 2533 | |
---|
2150 | | -static int i40e_intr_test(struct net_device *netdev, u64 *data) |
---|
| 2534 | +static u64 i40e_intr_test(struct net_device *netdev, u64 *data) |
---|
2151 | 2535 | { |
---|
2152 | 2536 | struct i40e_netdev_priv *np = netdev_priv(netdev); |
---|
2153 | 2537 | struct i40e_pf *pf = np->vsi->back; |
---|
.. | .. |
---|
2195 | 2579 | |
---|
2196 | 2580 | set_bit(__I40E_TESTING, pf->state); |
---|
2197 | 2581 | |
---|
| 2582 | + if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) || |
---|
| 2583 | + test_bit(__I40E_RESET_INTR_RECEIVED, pf->state)) { |
---|
| 2584 | + dev_warn(&pf->pdev->dev, |
---|
| 2585 | + "Cannot start offline testing when PF is in reset state.\n"); |
---|
| 2586 | + goto skip_ol_tests; |
---|
| 2587 | + } |
---|
| 2588 | + |
---|
2198 | 2589 | if (i40e_active_vfs(pf) || i40e_active_vmdqs(pf)) { |
---|
2199 | 2590 | dev_warn(&pf->pdev->dev, |
---|
2200 | 2591 | "Please take active VFs and Netqueues offline and restart the adapter before running NIC diagnostics\n"); |
---|
2201 | | - data[I40E_ETH_TEST_REG] = 1; |
---|
2202 | | - data[I40E_ETH_TEST_EEPROM] = 1; |
---|
2203 | | - data[I40E_ETH_TEST_INTR] = 1; |
---|
2204 | | - data[I40E_ETH_TEST_LINK] = 1; |
---|
2205 | | - eth_test->flags |= ETH_TEST_FL_FAILED; |
---|
2206 | | - clear_bit(__I40E_TESTING, pf->state); |
---|
2207 | 2592 | goto skip_ol_tests; |
---|
2208 | 2593 | } |
---|
2209 | 2594 | |
---|
.. | .. |
---|
2250 | 2635 | data[I40E_ETH_TEST_INTR] = 0; |
---|
2251 | 2636 | } |
---|
2252 | 2637 | |
---|
2253 | | -skip_ol_tests: |
---|
2254 | | - |
---|
2255 | 2638 | netif_info(pf, drv, netdev, "testing finished\n"); |
---|
| 2639 | + return; |
---|
| 2640 | + |
---|
| 2641 | +skip_ol_tests: |
---|
| 2642 | + data[I40E_ETH_TEST_REG] = 1; |
---|
| 2643 | + data[I40E_ETH_TEST_EEPROM] = 1; |
---|
| 2644 | + data[I40E_ETH_TEST_INTR] = 1; |
---|
| 2645 | + data[I40E_ETH_TEST_LINK] = 1; |
---|
| 2646 | + eth_test->flags |= ETH_TEST_FL_FAILED; |
---|
| 2647 | + clear_bit(__I40E_TESTING, pf->state); |
---|
| 2648 | + netif_info(pf, drv, netdev, "testing failed\n"); |
---|
2256 | 2649 | } |
---|
2257 | 2650 | |
---|
2258 | 2651 | static void i40e_get_wol(struct net_device *netdev, |
---|
.. | .. |
---|
2302 | 2695 | return -EOPNOTSUPP; |
---|
2303 | 2696 | |
---|
2304 | 2697 | /* only magic packet is supported */ |
---|
2305 | | - if (wol->wolopts && (wol->wolopts != WAKE_MAGIC)) |
---|
| 2698 | + if (wol->wolopts & ~WAKE_MAGIC) |
---|
2306 | 2699 | return -EOPNOTSUPP; |
---|
2307 | 2700 | |
---|
2308 | 2701 | /* is this a new value? */ |
---|
.. | .. |
---|
2363 | 2756 | default: |
---|
2364 | 2757 | break; |
---|
2365 | 2758 | } |
---|
2366 | | - if (ret) |
---|
2367 | | - return -ENOENT; |
---|
2368 | | - else |
---|
2369 | | - return 0; |
---|
| 2759 | + if (ret) |
---|
| 2760 | + return -ENOENT; |
---|
| 2761 | + else |
---|
| 2762 | + return 0; |
---|
2370 | 2763 | } |
---|
2371 | 2764 | |
---|
2372 | 2765 | /* NOTE: i40e hardware uses a conversion factor of 2 for Interrupt |
---|
.. | .. |
---|
2690 | 3083 | |
---|
2691 | 3084 | if (cmd->flow_type == TCP_V4_FLOW || |
---|
2692 | 3085 | cmd->flow_type == UDP_V4_FLOW) { |
---|
2693 | | - if (i_set & I40E_L3_SRC_MASK) |
---|
2694 | | - cmd->data |= RXH_IP_SRC; |
---|
2695 | | - if (i_set & I40E_L3_DST_MASK) |
---|
2696 | | - cmd->data |= RXH_IP_DST; |
---|
| 3086 | + if (hw->mac.type == I40E_MAC_X722) { |
---|
| 3087 | + if (i_set & I40E_X722_L3_SRC_MASK) |
---|
| 3088 | + cmd->data |= RXH_IP_SRC; |
---|
| 3089 | + if (i_set & I40E_X722_L3_DST_MASK) |
---|
| 3090 | + cmd->data |= RXH_IP_DST; |
---|
| 3091 | + } else { |
---|
| 3092 | + if (i_set & I40E_L3_SRC_MASK) |
---|
| 3093 | + cmd->data |= RXH_IP_SRC; |
---|
| 3094 | + if (i_set & I40E_L3_DST_MASK) |
---|
| 3095 | + cmd->data |= RXH_IP_DST; |
---|
| 3096 | + } |
---|
2697 | 3097 | } else if (cmd->flow_type == TCP_V6_FLOW || |
---|
2698 | 3098 | cmd->flow_type == UDP_V6_FLOW) { |
---|
2699 | 3099 | if (i_set & I40E_L3_V6_SRC_MASK) |
---|
.. | .. |
---|
3000 | 3400 | |
---|
3001 | 3401 | /** |
---|
3002 | 3402 | * i40e_get_rss_hash_bits - Read RSS Hash bits from register |
---|
| 3403 | + * @hw: hw structure |
---|
3003 | 3404 | * @nfc: pointer to user request |
---|
3004 | 3405 | * @i_setc: bits currently set |
---|
3005 | 3406 | * |
---|
3006 | 3407 | * Returns value of bits to be set per user request |
---|
3007 | 3408 | **/ |
---|
3008 | | -static u64 i40e_get_rss_hash_bits(struct ethtool_rxnfc *nfc, u64 i_setc) |
---|
| 3409 | +static u64 i40e_get_rss_hash_bits(struct i40e_hw *hw, |
---|
| 3410 | + struct ethtool_rxnfc *nfc, |
---|
| 3411 | + u64 i_setc) |
---|
3009 | 3412 | { |
---|
3010 | 3413 | u64 i_set = i_setc; |
---|
3011 | 3414 | u64 src_l3 = 0, dst_l3 = 0; |
---|
.. | .. |
---|
3024 | 3427 | dst_l3 = I40E_L3_V6_DST_MASK; |
---|
3025 | 3428 | } else if (nfc->flow_type == TCP_V4_FLOW || |
---|
3026 | 3429 | nfc->flow_type == UDP_V4_FLOW) { |
---|
3027 | | - src_l3 = I40E_L3_SRC_MASK; |
---|
3028 | | - dst_l3 = I40E_L3_DST_MASK; |
---|
| 3430 | + if (hw->mac.type == I40E_MAC_X722) { |
---|
| 3431 | + src_l3 = I40E_X722_L3_SRC_MASK; |
---|
| 3432 | + dst_l3 = I40E_X722_L3_DST_MASK; |
---|
| 3433 | + } else { |
---|
| 3434 | + src_l3 = I40E_L3_SRC_MASK; |
---|
| 3435 | + dst_l3 = I40E_L3_DST_MASK; |
---|
| 3436 | + } |
---|
3029 | 3437 | } else { |
---|
3030 | 3438 | /* Any other flow type are not supported here */ |
---|
3031 | 3439 | return i_set; |
---|
.. | .. |
---|
3043 | 3451 | return i_set; |
---|
3044 | 3452 | } |
---|
3045 | 3453 | |
---|
| 3454 | +#define FLOW_PCTYPES_SIZE 64 |
---|
3046 | 3455 | /** |
---|
3047 | 3456 | * i40e_set_rss_hash_opt - Enable/Disable flow types for RSS hash |
---|
3048 | 3457 | * @pf: pointer to the physical function struct |
---|
.. | .. |
---|
3055 | 3464 | struct i40e_hw *hw = &pf->hw; |
---|
3056 | 3465 | u64 hena = (u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0)) | |
---|
3057 | 3466 | ((u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1)) << 32); |
---|
3058 | | - u8 flow_pctype = 0; |
---|
| 3467 | + DECLARE_BITMAP(flow_pctypes, FLOW_PCTYPES_SIZE); |
---|
3059 | 3468 | u64 i_set, i_setc; |
---|
| 3469 | + |
---|
| 3470 | + bitmap_zero(flow_pctypes, FLOW_PCTYPES_SIZE); |
---|
3060 | 3471 | |
---|
3061 | 3472 | if (pf->flags & I40E_FLAG_MFP_ENABLED) { |
---|
3062 | 3473 | dev_err(&pf->pdev->dev, |
---|
.. | .. |
---|
3073 | 3484 | |
---|
3074 | 3485 | switch (nfc->flow_type) { |
---|
3075 | 3486 | case TCP_V4_FLOW: |
---|
3076 | | - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP; |
---|
| 3487 | + set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, flow_pctypes); |
---|
3077 | 3488 | if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) |
---|
3078 | | - hena |= |
---|
3079 | | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); |
---|
| 3489 | + set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK, |
---|
| 3490 | + flow_pctypes); |
---|
3080 | 3491 | break; |
---|
3081 | 3492 | case TCP_V6_FLOW: |
---|
3082 | | - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_TCP; |
---|
| 3493 | + set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, flow_pctypes); |
---|
3083 | 3494 | if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) |
---|
3084 | | - hena |= |
---|
3085 | | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); |
---|
3086 | | - if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) |
---|
3087 | | - hena |= |
---|
3088 | | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK); |
---|
| 3495 | + set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK, |
---|
| 3496 | + flow_pctypes); |
---|
3089 | 3497 | break; |
---|
3090 | 3498 | case UDP_V4_FLOW: |
---|
3091 | | - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; |
---|
3092 | | - if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) |
---|
3093 | | - hena |= |
---|
3094 | | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | |
---|
3095 | | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP); |
---|
3096 | | - |
---|
| 3499 | + set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, flow_pctypes); |
---|
| 3500 | + if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) { |
---|
| 3501 | + set_bit(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP, |
---|
| 3502 | + flow_pctypes); |
---|
| 3503 | + set_bit(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP, |
---|
| 3504 | + flow_pctypes); |
---|
| 3505 | + } |
---|
3097 | 3506 | hena |= BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4); |
---|
3098 | 3507 | break; |
---|
3099 | 3508 | case UDP_V6_FLOW: |
---|
3100 | | - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_UDP; |
---|
3101 | | - if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) |
---|
3102 | | - hena |= |
---|
3103 | | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | |
---|
3104 | | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP); |
---|
3105 | | - |
---|
| 3509 | + set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, flow_pctypes); |
---|
| 3510 | + if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) { |
---|
| 3511 | + set_bit(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP, |
---|
| 3512 | + flow_pctypes); |
---|
| 3513 | + set_bit(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP, |
---|
| 3514 | + flow_pctypes); |
---|
| 3515 | + } |
---|
3106 | 3516 | hena |= BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6); |
---|
3107 | 3517 | break; |
---|
3108 | 3518 | case AH_ESP_V4_FLOW: |
---|
.. | .. |
---|
3135 | 3545 | return -EINVAL; |
---|
3136 | 3546 | } |
---|
3137 | 3547 | |
---|
3138 | | - if (flow_pctype) { |
---|
3139 | | - i_setc = (u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, |
---|
3140 | | - flow_pctype)) | |
---|
3141 | | - ((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, |
---|
3142 | | - flow_pctype)) << 32); |
---|
3143 | | - i_set = i40e_get_rss_hash_bits(nfc, i_setc); |
---|
3144 | | - i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_pctype), |
---|
3145 | | - (u32)i_set); |
---|
3146 | | - i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype), |
---|
3147 | | - (u32)(i_set >> 32)); |
---|
3148 | | - hena |= BIT_ULL(flow_pctype); |
---|
| 3548 | + if (bitmap_weight(flow_pctypes, FLOW_PCTYPES_SIZE)) { |
---|
| 3549 | + u8 flow_id; |
---|
| 3550 | + |
---|
| 3551 | + for_each_set_bit(flow_id, flow_pctypes, FLOW_PCTYPES_SIZE) { |
---|
| 3552 | + i_setc = (u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_id)) | |
---|
| 3553 | + ((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_id)) << 32); |
---|
| 3554 | + i_set = i40e_get_rss_hash_bits(&pf->hw, nfc, i_setc); |
---|
| 3555 | + |
---|
| 3556 | + i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_id), |
---|
| 3557 | + (u32)i_set); |
---|
| 3558 | + i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_id), |
---|
| 3559 | + (u32)(i_set >> 32)); |
---|
| 3560 | + hena |= BIT_ULL(flow_id); |
---|
| 3561 | + } |
---|
3149 | 3562 | } |
---|
3150 | 3563 | |
---|
3151 | 3564 | i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (u32)hena); |
---|
.. | .. |
---|
3759 | 4172 | switch (fsp->flow_type & ~FLOW_EXT) { |
---|
3760 | 4173 | case SCTP_V4_FLOW: |
---|
3761 | 4174 | new_mask &= ~I40E_VERIFY_TAG_MASK; |
---|
3762 | | - /* Fall through */ |
---|
| 4175 | + fallthrough; |
---|
3763 | 4176 | case TCP_V4_FLOW: |
---|
3764 | 4177 | case UDP_V4_FLOW: |
---|
3765 | 4178 | tcp_ip4_spec = &fsp->m_u.tcp_ip4_spec; |
---|
.. | .. |
---|
3821 | 4234 | return -EOPNOTSUPP; |
---|
3822 | 4235 | |
---|
3823 | 4236 | /* First 4 bytes of L4 header */ |
---|
3824 | | - if (usr_ip4_spec->l4_4_bytes == htonl(0xFFFFFFFF)) |
---|
3825 | | - new_mask |= I40E_L4_SRC_MASK | I40E_L4_DST_MASK; |
---|
3826 | | - else if (!usr_ip4_spec->l4_4_bytes) |
---|
3827 | | - new_mask &= ~(I40E_L4_SRC_MASK | I40E_L4_DST_MASK); |
---|
3828 | | - else |
---|
| 4237 | + if (usr_ip4_spec->l4_4_bytes) |
---|
3829 | 4238 | return -EOPNOTSUPP; |
---|
3830 | 4239 | |
---|
3831 | 4240 | /* Filtering on Type of Service is not supported. */ |
---|
.. | .. |
---|
4528 | 4937 | static int i40e_set_priv_flags(struct net_device *dev, u32 flags) |
---|
4529 | 4938 | { |
---|
4530 | 4939 | struct i40e_netdev_priv *np = netdev_priv(dev); |
---|
| 4940 | + u64 orig_flags, new_flags, changed_flags; |
---|
| 4941 | + enum i40e_admin_queue_err adq_err; |
---|
4531 | 4942 | struct i40e_vsi *vsi = np->vsi; |
---|
4532 | 4943 | struct i40e_pf *pf = vsi->back; |
---|
4533 | | - u64 orig_flags, new_flags, changed_flags; |
---|
| 4944 | + u32 reset_needed = 0; |
---|
| 4945 | + i40e_status status; |
---|
4534 | 4946 | u32 i, j; |
---|
4535 | 4947 | |
---|
4536 | 4948 | orig_flags = READ_ONCE(pf->flags); |
---|
.. | .. |
---|
4574 | 4986 | flags_complete: |
---|
4575 | 4987 | changed_flags = orig_flags ^ new_flags; |
---|
4576 | 4988 | |
---|
| 4989 | + if (changed_flags & I40E_FLAG_DISABLE_FW_LLDP) |
---|
| 4990 | + reset_needed = I40E_PF_RESET_AND_REBUILD_FLAG; |
---|
| 4991 | + if (changed_flags & (I40E_FLAG_VEB_STATS_ENABLED | |
---|
| 4992 | + I40E_FLAG_LEGACY_RX | I40E_FLAG_SOURCE_PRUNING_DISABLED)) |
---|
| 4993 | + reset_needed = BIT(__I40E_PF_RESET_REQUESTED); |
---|
| 4994 | + |
---|
4577 | 4995 | /* Before we finalize any flag changes, we need to perform some |
---|
4578 | 4996 | * checks to ensure that the changes are supported and safe. |
---|
4579 | 4997 | */ |
---|
.. | .. |
---|
4584 | 5002 | return -EOPNOTSUPP; |
---|
4585 | 5003 | |
---|
4586 | 5004 | /* If the driver detected FW LLDP was disabled on init, this flag could |
---|
4587 | | - * be set, however we do not support _changing_ the flag if NPAR is |
---|
4588 | | - * enabled or FW API version < 1.7. There are situations where older |
---|
4589 | | - * FW versions/NPAR enabled PFs could disable LLDP, however we _must_ |
---|
4590 | | - * not allow the user to enable/disable LLDP with this flag on |
---|
4591 | | - * unsupported FW versions. |
---|
| 5005 | + * be set, however we do not support _changing_ the flag: |
---|
| 5006 | + * - on XL710 if NPAR is enabled or FW API version < 1.7 |
---|
| 5007 | + * - on X722 with FW API version < 1.6 |
---|
| 5008 | + * There are situations where older FW versions/NPAR enabled PFs could |
---|
| 5009 | + * disable LLDP, however we _must_ not allow the user to enable/disable |
---|
| 5010 | + * LLDP with this flag on unsupported FW versions. |
---|
4592 | 5011 | */ |
---|
4593 | 5012 | if (changed_flags & I40E_FLAG_DISABLE_FW_LLDP) { |
---|
4594 | | - if (!(pf->hw_features & I40E_HW_STOPPABLE_FW_LLDP)) { |
---|
| 5013 | + if (!(pf->hw.flags & I40E_HW_FLAG_FW_LLDP_STOPPABLE)) { |
---|
4595 | 5014 | dev_warn(&pf->pdev->dev, |
---|
4596 | 5015 | "Device does not support changing FW LLDP\n"); |
---|
4597 | 5016 | return -EOPNOTSUPP; |
---|
4598 | 5017 | } |
---|
4599 | 5018 | } |
---|
4600 | 5019 | |
---|
4601 | | - /* Now that we've checked to ensure that the new flags are valid, load |
---|
4602 | | - * them into place. Since we only modify flags either (a) during |
---|
4603 | | - * initialization or (b) while holding the RTNL lock, we don't need |
---|
4604 | | - * anything fancy here. |
---|
4605 | | - */ |
---|
4606 | | - pf->flags = new_flags; |
---|
| 5020 | + if (changed_flags & I40E_FLAG_RS_FEC && |
---|
| 5021 | + pf->hw.device_id != I40E_DEV_ID_25G_SFP28 && |
---|
| 5022 | + pf->hw.device_id != I40E_DEV_ID_25G_B) { |
---|
| 5023 | + dev_warn(&pf->pdev->dev, |
---|
| 5024 | + "Device does not support changing FEC configuration\n"); |
---|
| 5025 | + return -EOPNOTSUPP; |
---|
| 5026 | + } |
---|
| 5027 | + |
---|
| 5028 | + if (changed_flags & I40E_FLAG_BASE_R_FEC && |
---|
| 5029 | + pf->hw.device_id != I40E_DEV_ID_25G_SFP28 && |
---|
| 5030 | + pf->hw.device_id != I40E_DEV_ID_25G_B && |
---|
| 5031 | + pf->hw.device_id != I40E_DEV_ID_KX_X722) { |
---|
| 5032 | + dev_warn(&pf->pdev->dev, |
---|
| 5033 | + "Device does not support changing FEC configuration\n"); |
---|
| 5034 | + return -EOPNOTSUPP; |
---|
| 5035 | + } |
---|
4607 | 5036 | |
---|
4608 | 5037 | /* Process any additional changes needed as a result of flag changes. |
---|
4609 | 5038 | * The changed_flags value reflects the list of bits that were |
---|
.. | .. |
---|
4612 | 5041 | |
---|
4613 | 5042 | /* Flush current ATR settings if ATR was disabled */ |
---|
4614 | 5043 | if ((changed_flags & I40E_FLAG_FD_ATR_ENABLED) && |
---|
4615 | | - !(pf->flags & I40E_FLAG_FD_ATR_ENABLED)) { |
---|
| 5044 | + !(new_flags & I40E_FLAG_FD_ATR_ENABLED)) { |
---|
4616 | 5045 | set_bit(__I40E_FD_ATR_AUTO_DISABLED, pf->state); |
---|
4617 | 5046 | set_bit(__I40E_FD_FLUSH_REQUESTED, pf->state); |
---|
4618 | 5047 | } |
---|
.. | .. |
---|
4621 | 5050 | u16 sw_flags = 0, valid_flags = 0; |
---|
4622 | 5051 | int ret; |
---|
4623 | 5052 | |
---|
4624 | | - if (!(pf->flags & I40E_FLAG_TRUE_PROMISC_SUPPORT)) |
---|
| 5053 | + if (!(new_flags & I40E_FLAG_TRUE_PROMISC_SUPPORT)) |
---|
4625 | 5054 | sw_flags = I40E_AQ_SET_SWITCH_CFG_PROMISC; |
---|
4626 | 5055 | valid_flags = I40E_AQ_SET_SWITCH_CFG_PROMISC; |
---|
4627 | 5056 | ret = i40e_aq_set_switch_config(&pf->hw, sw_flags, valid_flags, |
---|
.. | .. |
---|
4636 | 5065 | } |
---|
4637 | 5066 | } |
---|
4638 | 5067 | |
---|
4639 | | - if ((changed_flags & pf->flags & |
---|
| 5068 | + if ((changed_flags & I40E_FLAG_RS_FEC) || |
---|
| 5069 | + (changed_flags & I40E_FLAG_BASE_R_FEC)) { |
---|
| 5070 | + u8 fec_cfg = 0; |
---|
| 5071 | + |
---|
| 5072 | + if (new_flags & I40E_FLAG_RS_FEC && |
---|
| 5073 | + new_flags & I40E_FLAG_BASE_R_FEC) { |
---|
| 5074 | + fec_cfg = I40E_AQ_SET_FEC_AUTO; |
---|
| 5075 | + } else if (new_flags & I40E_FLAG_RS_FEC) { |
---|
| 5076 | + fec_cfg = (I40E_AQ_SET_FEC_REQUEST_RS | |
---|
| 5077 | + I40E_AQ_SET_FEC_ABILITY_RS); |
---|
| 5078 | + } else if (new_flags & I40E_FLAG_BASE_R_FEC) { |
---|
| 5079 | + fec_cfg = (I40E_AQ_SET_FEC_REQUEST_KR | |
---|
| 5080 | + I40E_AQ_SET_FEC_ABILITY_KR); |
---|
| 5081 | + } |
---|
| 5082 | + if (i40e_set_fec_cfg(dev, fec_cfg)) |
---|
| 5083 | + dev_warn(&pf->pdev->dev, "Cannot change FEC config\n"); |
---|
| 5084 | + } |
---|
| 5085 | + |
---|
| 5086 | + if ((changed_flags & I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED) && |
---|
| 5087 | + (orig_flags & I40E_FLAG_TOTAL_PORT_SHUTDOWN_ENABLED)) { |
---|
| 5088 | + dev_err(&pf->pdev->dev, |
---|
| 5089 | + "Setting link-down-on-close not supported on this port (because total-port-shutdown is enabled)\n"); |
---|
| 5090 | + return -EOPNOTSUPP; |
---|
| 5091 | + } |
---|
| 5092 | + |
---|
| 5093 | + if ((changed_flags & new_flags & |
---|
4640 | 5094 | I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED) && |
---|
4641 | | - (pf->flags & I40E_FLAG_MFP_ENABLED)) |
---|
| 5095 | + (new_flags & I40E_FLAG_MFP_ENABLED)) |
---|
4642 | 5096 | dev_warn(&pf->pdev->dev, |
---|
4643 | 5097 | "Turning on link-down-on-close flag may affect other partitions\n"); |
---|
4644 | 5098 | |
---|
4645 | 5099 | if (changed_flags & I40E_FLAG_DISABLE_FW_LLDP) { |
---|
4646 | | - if (pf->flags & I40E_FLAG_DISABLE_FW_LLDP) { |
---|
| 5100 | + if (new_flags & I40E_FLAG_DISABLE_FW_LLDP) { |
---|
4647 | 5101 | struct i40e_dcbx_config *dcbcfg; |
---|
4648 | 5102 | |
---|
4649 | | - i40e_aq_stop_lldp(&pf->hw, true, NULL); |
---|
| 5103 | + i40e_aq_stop_lldp(&pf->hw, true, false, NULL); |
---|
4650 | 5104 | i40e_aq_set_dcb_parameters(&pf->hw, true, NULL); |
---|
4651 | 5105 | /* reset local_dcbx_config to default */ |
---|
4652 | 5106 | dcbcfg = &pf->hw.local_dcbx_config; |
---|
.. | .. |
---|
4661 | 5115 | dcbcfg->pfc.willing = 1; |
---|
4662 | 5116 | dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; |
---|
4663 | 5117 | } else { |
---|
4664 | | - i40e_aq_start_lldp(&pf->hw, NULL); |
---|
| 5118 | + status = i40e_aq_start_lldp(&pf->hw, false, NULL); |
---|
| 5119 | + if (status) { |
---|
| 5120 | + adq_err = pf->hw.aq.asq_last_status; |
---|
| 5121 | + switch (adq_err) { |
---|
| 5122 | + case I40E_AQ_RC_EEXIST: |
---|
| 5123 | + dev_warn(&pf->pdev->dev, |
---|
| 5124 | + "FW LLDP agent is already running\n"); |
---|
| 5125 | + reset_needed = 0; |
---|
| 5126 | + break; |
---|
| 5127 | + case I40E_AQ_RC_EPERM: |
---|
| 5128 | + dev_warn(&pf->pdev->dev, |
---|
| 5129 | + "Device configuration forbids SW from starting the LLDP agent.\n"); |
---|
| 5130 | + return -EINVAL; |
---|
| 5131 | + case I40E_AQ_RC_EAGAIN: |
---|
| 5132 | + dev_warn(&pf->pdev->dev, |
---|
| 5133 | + "Stop FW LLDP agent command is still being processed, please try again in a second.\n"); |
---|
| 5134 | + return -EBUSY; |
---|
| 5135 | + default: |
---|
| 5136 | + dev_warn(&pf->pdev->dev, |
---|
| 5137 | + "Starting FW LLDP agent failed: error: %s, %s\n", |
---|
| 5138 | + i40e_stat_str(&pf->hw, |
---|
| 5139 | + status), |
---|
| 5140 | + i40e_aq_str(&pf->hw, |
---|
| 5141 | + adq_err)); |
---|
| 5142 | + return -EINVAL; |
---|
| 5143 | + } |
---|
| 5144 | + } |
---|
4665 | 5145 | } |
---|
4666 | 5146 | } |
---|
| 5147 | + |
---|
| 5148 | + /* Now that we've checked to ensure that the new flags are valid, load |
---|
| 5149 | + * them into place. Since we only modify flags either (a) during |
---|
| 5150 | + * initialization or (b) while holding the RTNL lock, we don't need |
---|
| 5151 | + * anything fancy here. |
---|
| 5152 | + */ |
---|
| 5153 | + pf->flags = new_flags; |
---|
4667 | 5154 | |
---|
4668 | 5155 | /* Issue reset to cause things to take effect, as additional bits |
---|
4669 | 5156 | * are added we will need to create a mask of bits requiring reset |
---|
4670 | 5157 | */ |
---|
4671 | | - if (changed_flags & (I40E_FLAG_VEB_STATS_ENABLED | |
---|
4672 | | - I40E_FLAG_LEGACY_RX | |
---|
4673 | | - I40E_FLAG_SOURCE_PRUNING_DISABLED | |
---|
4674 | | - I40E_FLAG_DISABLE_FW_LLDP)) |
---|
4675 | | - i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED), true); |
---|
| 5158 | + if (reset_needed) |
---|
| 5159 | + i40e_do_reset(pf, reset_needed, true); |
---|
4676 | 5160 | |
---|
4677 | 5161 | return 0; |
---|
4678 | 5162 | } |
---|
.. | .. |
---|
4716 | 5200 | case I40E_MODULE_TYPE_SFP: |
---|
4717 | 5201 | status = i40e_aq_get_phy_register(hw, |
---|
4718 | 5202 | I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE, |
---|
4719 | | - I40E_I2C_EEPROM_DEV_ADDR, |
---|
| 5203 | + I40E_I2C_EEPROM_DEV_ADDR, true, |
---|
4720 | 5204 | I40E_MODULE_SFF_8472_COMP, |
---|
4721 | 5205 | &sff8472_comp, NULL); |
---|
4722 | 5206 | if (status) |
---|
.. | .. |
---|
4724 | 5208 | |
---|
4725 | 5209 | status = i40e_aq_get_phy_register(hw, |
---|
4726 | 5210 | I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE, |
---|
4727 | | - I40E_I2C_EEPROM_DEV_ADDR, |
---|
| 5211 | + I40E_I2C_EEPROM_DEV_ADDR, true, |
---|
4728 | 5212 | I40E_MODULE_SFF_8472_SWAP, |
---|
4729 | 5213 | &sff8472_swap, NULL); |
---|
4730 | 5214 | if (status) |
---|
.. | .. |
---|
4741 | 5225 | /* Module is not SFF-8472 compliant */ |
---|
4742 | 5226 | modinfo->type = ETH_MODULE_SFF_8079; |
---|
4743 | 5227 | modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; |
---|
| 5228 | + } else if (!(sff8472_swap & I40E_MODULE_SFF_DDM_IMPLEMENTED)) { |
---|
| 5229 | + /* Module is SFF-8472 compliant but doesn't implement |
---|
| 5230 | + * Digital Diagnostic Monitoring (DDM). |
---|
| 5231 | + */ |
---|
| 5232 | + modinfo->type = ETH_MODULE_SFF_8079; |
---|
| 5233 | + modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; |
---|
4744 | 5234 | } else { |
---|
4745 | 5235 | modinfo->type = ETH_MODULE_SFF_8472; |
---|
4746 | 5236 | modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; |
---|
.. | .. |
---|
4750 | 5240 | /* Read from memory page 0. */ |
---|
4751 | 5241 | status = i40e_aq_get_phy_register(hw, |
---|
4752 | 5242 | I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE, |
---|
4753 | | - 0, |
---|
| 5243 | + 0, true, |
---|
4754 | 5244 | I40E_MODULE_REVISION_ADDR, |
---|
4755 | 5245 | &sff8636_rev, NULL); |
---|
4756 | 5246 | if (status) |
---|
.. | .. |
---|
4821 | 5311 | |
---|
4822 | 5312 | status = i40e_aq_get_phy_register(hw, |
---|
4823 | 5313 | I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE, |
---|
4824 | | - addr, offset, &value, NULL); |
---|
| 5314 | + addr, true, offset, &value, NULL); |
---|
4825 | 5315 | if (status) |
---|
4826 | 5316 | return -EIO; |
---|
4827 | 5317 | data[i] = value; |
---|
.. | .. |
---|
4829 | 5319 | return 0; |
---|
4830 | 5320 | } |
---|
4831 | 5321 | |
---|
| 5322 | +static int i40e_get_eee(struct net_device *netdev, struct ethtool_eee *edata) |
---|
| 5323 | +{ |
---|
| 5324 | + return -EOPNOTSUPP; |
---|
| 5325 | +} |
---|
| 5326 | + |
---|
| 5327 | +static int i40e_set_eee(struct net_device *netdev, struct ethtool_eee *edata) |
---|
| 5328 | +{ |
---|
| 5329 | + return -EOPNOTSUPP; |
---|
| 5330 | +} |
---|
| 5331 | + |
---|
| 5332 | +static const struct ethtool_ops i40e_ethtool_recovery_mode_ops = { |
---|
| 5333 | + .get_drvinfo = i40e_get_drvinfo, |
---|
| 5334 | + .set_eeprom = i40e_set_eeprom, |
---|
| 5335 | + .get_eeprom_len = i40e_get_eeprom_len, |
---|
| 5336 | + .get_eeprom = i40e_get_eeprom, |
---|
| 5337 | +}; |
---|
| 5338 | + |
---|
4832 | 5339 | static const struct ethtool_ops i40e_ethtool_ops = { |
---|
| 5340 | + .supported_coalesce_params = ETHTOOL_COALESCE_USECS | |
---|
| 5341 | + ETHTOOL_COALESCE_MAX_FRAMES_IRQ | |
---|
| 5342 | + ETHTOOL_COALESCE_USE_ADAPTIVE | |
---|
| 5343 | + ETHTOOL_COALESCE_RX_USECS_HIGH | |
---|
| 5344 | + ETHTOOL_COALESCE_TX_USECS_HIGH, |
---|
4833 | 5345 | .get_drvinfo = i40e_get_drvinfo, |
---|
4834 | 5346 | .get_regs_len = i40e_get_regs_len, |
---|
4835 | 5347 | .get_regs = i40e_get_regs, |
---|
.. | .. |
---|
4850 | 5362 | .set_rxnfc = i40e_set_rxnfc, |
---|
4851 | 5363 | .self_test = i40e_diag_test, |
---|
4852 | 5364 | .get_strings = i40e_get_strings, |
---|
| 5365 | + .get_eee = i40e_get_eee, |
---|
| 5366 | + .set_eee = i40e_set_eee, |
---|
4853 | 5367 | .set_phys_id = i40e_set_phys_id, |
---|
4854 | 5368 | .get_sset_count = i40e_get_sset_count, |
---|
4855 | 5369 | .get_ethtool_stats = i40e_get_ethtool_stats, |
---|
.. | .. |
---|
4870 | 5384 | .set_per_queue_coalesce = i40e_set_per_queue_coalesce, |
---|
4871 | 5385 | .get_link_ksettings = i40e_get_link_ksettings, |
---|
4872 | 5386 | .set_link_ksettings = i40e_set_link_ksettings, |
---|
| 5387 | + .get_fecparam = i40e_get_fec_param, |
---|
| 5388 | + .set_fecparam = i40e_set_fec_param, |
---|
| 5389 | + .flash_device = i40e_ddp_flash, |
---|
4873 | 5390 | }; |
---|
4874 | 5391 | |
---|
4875 | 5392 | void i40e_set_ethtool_ops(struct net_device *netdev) |
---|
4876 | 5393 | { |
---|
4877 | | - netdev->ethtool_ops = &i40e_ethtool_ops; |
---|
| 5394 | + struct i40e_netdev_priv *np = netdev_priv(netdev); |
---|
| 5395 | + struct i40e_pf *pf = np->vsi->back; |
---|
| 5396 | + |
---|
| 5397 | + if (!test_bit(__I40E_RECOVERY_MODE, pf->state)) |
---|
| 5398 | + netdev->ethtool_ops = &i40e_ethtool_ops; |
---|
| 5399 | + else |
---|
| 5400 | + netdev->ethtool_ops = &i40e_ethtool_recovery_mode_ops; |
---|
4878 | 5401 | } |
---|