| .. | .. |
|---|
| 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 | } |
|---|