.. | .. |
---|
1 | | -/* |
---|
2 | | - * aQuantia Corporation Network Driver |
---|
3 | | - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
| 2 | +/* Atlantic Network Driver |
---|
4 | 3 | * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms and conditions of the GNU General Public License, |
---|
7 | | - * version 2, as published by the Free Software Foundation. |
---|
| 4 | + * Copyright (C) 2014-2019 aQuantia Corporation |
---|
| 5 | + * Copyright (C) 2019-2020 Marvell International Ltd. |
---|
8 | 6 | */ |
---|
9 | 7 | |
---|
10 | 8 | /* File aq_ethtool.c: Definition of ethertool related functions. */ |
---|
.. | .. |
---|
12 | 10 | #include "aq_ethtool.h" |
---|
13 | 11 | #include "aq_nic.h" |
---|
14 | 12 | #include "aq_vec.h" |
---|
| 13 | +#include "aq_ptp.h" |
---|
| 14 | +#include "aq_filters.h" |
---|
| 15 | +#include "aq_macsec.h" |
---|
| 16 | +#include "aq_main.h" |
---|
| 17 | + |
---|
| 18 | +#include <linux/ptp_clock_kernel.h> |
---|
15 | 19 | |
---|
16 | 20 | static void aq_ethtool_get_regs(struct net_device *ndev, |
---|
17 | 21 | struct ethtool_regs *regs, void *p) |
---|
18 | 22 | { |
---|
19 | 23 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
20 | | - u32 regs_count = aq_nic_get_regs_count(aq_nic); |
---|
| 24 | + u32 regs_count; |
---|
| 25 | + |
---|
| 26 | + regs_count = aq_nic_get_regs_count(aq_nic); |
---|
21 | 27 | |
---|
22 | 28 | memset(p, 0, regs_count * sizeof(u32)); |
---|
23 | 29 | aq_nic_get_regs(aq_nic, regs, p); |
---|
.. | .. |
---|
26 | 32 | static int aq_ethtool_get_regs_len(struct net_device *ndev) |
---|
27 | 33 | { |
---|
28 | 34 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
29 | | - u32 regs_count = aq_nic_get_regs_count(aq_nic); |
---|
| 35 | + u32 regs_count; |
---|
| 36 | + |
---|
| 37 | + regs_count = aq_nic_get_regs_count(aq_nic); |
---|
30 | 38 | |
---|
31 | 39 | return regs_count * sizeof(u32); |
---|
32 | 40 | } |
---|
.. | .. |
---|
82 | 90 | "InDroppedDma", |
---|
83 | 91 | }; |
---|
84 | 92 | |
---|
85 | | -static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = { |
---|
86 | | - "Queue[%d] InPackets", |
---|
87 | | - "Queue[%d] OutPackets", |
---|
88 | | - "Queue[%d] Restarts", |
---|
89 | | - "Queue[%d] InJumboPackets", |
---|
90 | | - "Queue[%d] InLroPackets", |
---|
91 | | - "Queue[%d] InErrors", |
---|
| 93 | +static const char * const aq_ethtool_queue_rx_stat_names[] = { |
---|
| 94 | + "%sQueue[%d] InPackets", |
---|
| 95 | + "%sQueue[%d] InJumboPackets", |
---|
| 96 | + "%sQueue[%d] InLroPackets", |
---|
| 97 | + "%sQueue[%d] InErrors", |
---|
| 98 | + "%sQueue[%d] AllocFails", |
---|
| 99 | + "%sQueue[%d] SkbAllocFails", |
---|
| 100 | + "%sQueue[%d] Polls", |
---|
92 | 101 | }; |
---|
| 102 | + |
---|
| 103 | +static const char * const aq_ethtool_queue_tx_stat_names[] = { |
---|
| 104 | + "%sQueue[%d] OutPackets", |
---|
| 105 | + "%sQueue[%d] Restarts", |
---|
| 106 | +}; |
---|
| 107 | + |
---|
| 108 | +#if IS_ENABLED(CONFIG_MACSEC) |
---|
| 109 | +static const char aq_macsec_stat_names[][ETH_GSTRING_LEN] = { |
---|
| 110 | + "MACSec InCtlPackets", |
---|
| 111 | + "MACSec InTaggedMissPackets", |
---|
| 112 | + "MACSec InUntaggedMissPackets", |
---|
| 113 | + "MACSec InNotagPackets", |
---|
| 114 | + "MACSec InUntaggedPackets", |
---|
| 115 | + "MACSec InBadTagPackets", |
---|
| 116 | + "MACSec InNoSciPackets", |
---|
| 117 | + "MACSec InUnknownSciPackets", |
---|
| 118 | + "MACSec InCtrlPortPassPackets", |
---|
| 119 | + "MACSec InUnctrlPortPassPackets", |
---|
| 120 | + "MACSec InCtrlPortFailPackets", |
---|
| 121 | + "MACSec InUnctrlPortFailPackets", |
---|
| 122 | + "MACSec InTooLongPackets", |
---|
| 123 | + "MACSec InIgpocCtlPackets", |
---|
| 124 | + "MACSec InEccErrorPackets", |
---|
| 125 | + "MACSec InUnctrlHitDropRedir", |
---|
| 126 | + "MACSec OutCtlPackets", |
---|
| 127 | + "MACSec OutUnknownSaPackets", |
---|
| 128 | + "MACSec OutUntaggedPackets", |
---|
| 129 | + "MACSec OutTooLong", |
---|
| 130 | + "MACSec OutEccErrorPackets", |
---|
| 131 | + "MACSec OutUnctrlHitDropRedir", |
---|
| 132 | +}; |
---|
| 133 | + |
---|
| 134 | +static const char * const aq_macsec_txsc_stat_names[] = { |
---|
| 135 | + "MACSecTXSC%d ProtectedPkts", |
---|
| 136 | + "MACSecTXSC%d EncryptedPkts", |
---|
| 137 | + "MACSecTXSC%d ProtectedOctets", |
---|
| 138 | + "MACSecTXSC%d EncryptedOctets", |
---|
| 139 | +}; |
---|
| 140 | + |
---|
| 141 | +static const char * const aq_macsec_txsa_stat_names[] = { |
---|
| 142 | + "MACSecTXSC%dSA%d HitDropRedirect", |
---|
| 143 | + "MACSecTXSC%dSA%d Protected2Pkts", |
---|
| 144 | + "MACSecTXSC%dSA%d ProtectedPkts", |
---|
| 145 | + "MACSecTXSC%dSA%d EncryptedPkts", |
---|
| 146 | +}; |
---|
| 147 | + |
---|
| 148 | +static const char * const aq_macsec_rxsa_stat_names[] = { |
---|
| 149 | + "MACSecRXSC%dSA%d UntaggedHitPkts", |
---|
| 150 | + "MACSecRXSC%dSA%d CtrlHitDrpRedir", |
---|
| 151 | + "MACSecRXSC%dSA%d NotUsingSa", |
---|
| 152 | + "MACSecRXSC%dSA%d UnusedSa", |
---|
| 153 | + "MACSecRXSC%dSA%d NotValidPkts", |
---|
| 154 | + "MACSecRXSC%dSA%d InvalidPkts", |
---|
| 155 | + "MACSecRXSC%dSA%d OkPkts", |
---|
| 156 | + "MACSecRXSC%dSA%d LatePkts", |
---|
| 157 | + "MACSecRXSC%dSA%d DelayedPkts", |
---|
| 158 | + "MACSecRXSC%dSA%d UncheckedPkts", |
---|
| 159 | + "MACSecRXSC%dSA%d ValidatedOctets", |
---|
| 160 | + "MACSecRXSC%dSA%d DecryptedOctets", |
---|
| 161 | +}; |
---|
| 162 | +#endif |
---|
| 163 | + |
---|
| 164 | +static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = { |
---|
| 165 | + "DMASystemLoopback", |
---|
| 166 | + "PKTSystemLoopback", |
---|
| 167 | + "DMANetworkLoopback", |
---|
| 168 | + "PHYInternalLoopback", |
---|
| 169 | + "PHYExternalLoopback", |
---|
| 170 | +}; |
---|
| 171 | + |
---|
| 172 | +static u32 aq_ethtool_n_stats(struct net_device *ndev) |
---|
| 173 | +{ |
---|
| 174 | + const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names); |
---|
| 175 | + const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names); |
---|
| 176 | + struct aq_nic_s *nic = netdev_priv(ndev); |
---|
| 177 | + struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic); |
---|
| 178 | + u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + |
---|
| 179 | + (rx_stat_cnt + tx_stat_cnt) * cfg->vecs * cfg->tcs; |
---|
| 180 | + |
---|
| 181 | +#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) |
---|
| 182 | + n_stats += rx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_RX) + |
---|
| 183 | + tx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_TX); |
---|
| 184 | +#endif |
---|
| 185 | + |
---|
| 186 | +#if IS_ENABLED(CONFIG_MACSEC) |
---|
| 187 | + if (nic->macsec_cfg) { |
---|
| 188 | + n_stats += ARRAY_SIZE(aq_macsec_stat_names) + |
---|
| 189 | + ARRAY_SIZE(aq_macsec_txsc_stat_names) * |
---|
| 190 | + aq_macsec_tx_sc_cnt(nic) + |
---|
| 191 | + ARRAY_SIZE(aq_macsec_txsa_stat_names) * |
---|
| 192 | + aq_macsec_tx_sa_cnt(nic) + |
---|
| 193 | + ARRAY_SIZE(aq_macsec_rxsa_stat_names) * |
---|
| 194 | + aq_macsec_rx_sa_cnt(nic); |
---|
| 195 | + } |
---|
| 196 | +#endif |
---|
| 197 | + |
---|
| 198 | + return n_stats; |
---|
| 199 | +} |
---|
93 | 200 | |
---|
94 | 201 | static void aq_ethtool_stats(struct net_device *ndev, |
---|
95 | 202 | struct ethtool_stats *stats, u64 *data) |
---|
96 | 203 | { |
---|
97 | 204 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
98 | | - struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); |
---|
99 | 205 | |
---|
100 | | - memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) + |
---|
101 | | - ARRAY_SIZE(aq_ethtool_queue_stat_names) * |
---|
102 | | - cfg->vecs) * sizeof(u64)); |
---|
103 | | - aq_nic_get_stats(aq_nic, data); |
---|
| 206 | + memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64)); |
---|
| 207 | + data = aq_nic_get_stats(aq_nic, data); |
---|
| 208 | +#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) |
---|
| 209 | + data = aq_ptp_get_stats(aq_nic, data); |
---|
| 210 | +#endif |
---|
| 211 | +#if IS_ENABLED(CONFIG_MACSEC) |
---|
| 212 | + data = aq_macsec_get_stats(aq_nic, data); |
---|
| 213 | +#endif |
---|
104 | 214 | } |
---|
105 | 215 | |
---|
106 | 216 | static void aq_ethtool_get_drvinfo(struct net_device *ndev, |
---|
107 | 217 | struct ethtool_drvinfo *drvinfo) |
---|
108 | 218 | { |
---|
109 | | - struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
110 | | - struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); |
---|
111 | 219 | struct pci_dev *pdev = to_pci_dev(ndev->dev.parent); |
---|
112 | | - u32 firmware_version = aq_nic_get_fw_version(aq_nic); |
---|
113 | | - u32 regs_count = aq_nic_get_regs_count(aq_nic); |
---|
| 220 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 221 | + u32 firmware_version; |
---|
| 222 | + u32 regs_count; |
---|
| 223 | + |
---|
| 224 | + firmware_version = aq_nic_get_fw_version(aq_nic); |
---|
| 225 | + regs_count = aq_nic_get_regs_count(aq_nic); |
---|
114 | 226 | |
---|
115 | 227 | strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver)); |
---|
116 | | - strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version)); |
---|
117 | 228 | |
---|
118 | 229 | snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), |
---|
119 | 230 | "%u.%u.%u", firmware_version >> 24, |
---|
.. | .. |
---|
121 | 232 | |
---|
122 | 233 | strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "", |
---|
123 | 234 | sizeof(drvinfo->bus_info)); |
---|
124 | | - drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + |
---|
125 | | - cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); |
---|
| 235 | + drvinfo->n_stats = aq_ethtool_n_stats(ndev); |
---|
126 | 236 | drvinfo->testinfo_len = 0; |
---|
127 | 237 | drvinfo->regdump_len = regs_count; |
---|
128 | 238 | drvinfo->eedump_len = 0; |
---|
.. | .. |
---|
131 | 241 | static void aq_ethtool_get_strings(struct net_device *ndev, |
---|
132 | 242 | u32 stringset, u8 *data) |
---|
133 | 243 | { |
---|
134 | | - int i, si; |
---|
135 | | - struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
136 | | - struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); |
---|
| 244 | + struct aq_nic_s *nic = netdev_priv(ndev); |
---|
| 245 | + struct aq_nic_cfg_s *cfg; |
---|
137 | 246 | u8 *p = data; |
---|
| 247 | + int i, si; |
---|
| 248 | +#if IS_ENABLED(CONFIG_MACSEC) |
---|
| 249 | + int sa; |
---|
| 250 | +#endif |
---|
138 | 251 | |
---|
139 | | - if (stringset == ETH_SS_STATS) { |
---|
140 | | - memcpy(p, *aq_ethtool_stat_names, |
---|
| 252 | + cfg = aq_nic_get_cfg(nic); |
---|
| 253 | + |
---|
| 254 | + switch (stringset) { |
---|
| 255 | + case ETH_SS_STATS: { |
---|
| 256 | + const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names); |
---|
| 257 | + const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names); |
---|
| 258 | + char tc_string[8]; |
---|
| 259 | + int tc; |
---|
| 260 | + |
---|
| 261 | + memset(tc_string, 0, sizeof(tc_string)); |
---|
| 262 | + memcpy(p, aq_ethtool_stat_names, |
---|
141 | 263 | sizeof(aq_ethtool_stat_names)); |
---|
142 | 264 | p = p + sizeof(aq_ethtool_stat_names); |
---|
143 | | - for (i = 0; i < cfg->vecs; i++) { |
---|
144 | | - for (si = 0; |
---|
145 | | - si < ARRAY_SIZE(aq_ethtool_queue_stat_names); |
---|
146 | | - si++) { |
---|
147 | | - snprintf(p, ETH_GSTRING_LEN, |
---|
148 | | - aq_ethtool_queue_stat_names[si], i); |
---|
149 | | - p += ETH_GSTRING_LEN; |
---|
| 265 | + |
---|
| 266 | + for (tc = 0; tc < cfg->tcs; tc++) { |
---|
| 267 | + if (cfg->is_qos) |
---|
| 268 | + snprintf(tc_string, 8, "TC%d ", tc); |
---|
| 269 | + |
---|
| 270 | + for (i = 0; i < cfg->vecs; i++) { |
---|
| 271 | + for (si = 0; si < rx_stat_cnt; si++) { |
---|
| 272 | + snprintf(p, ETH_GSTRING_LEN, |
---|
| 273 | + aq_ethtool_queue_rx_stat_names[si], |
---|
| 274 | + tc_string, |
---|
| 275 | + AQ_NIC_CFG_TCVEC2RING(cfg, tc, i)); |
---|
| 276 | + p += ETH_GSTRING_LEN; |
---|
| 277 | + } |
---|
| 278 | + for (si = 0; si < tx_stat_cnt; si++) { |
---|
| 279 | + snprintf(p, ETH_GSTRING_LEN, |
---|
| 280 | + aq_ethtool_queue_tx_stat_names[si], |
---|
| 281 | + tc_string, |
---|
| 282 | + AQ_NIC_CFG_TCVEC2RING(cfg, tc, i)); |
---|
| 283 | + p += ETH_GSTRING_LEN; |
---|
| 284 | + } |
---|
150 | 285 | } |
---|
151 | 286 | } |
---|
| 287 | +#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) |
---|
| 288 | + if (nic->aq_ptp) { |
---|
| 289 | + const int rx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_RX); |
---|
| 290 | + const int tx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_TX); |
---|
| 291 | + unsigned int ptp_ring_idx = |
---|
| 292 | + aq_ptp_ring_idx(nic->aq_nic_cfg.tc_mode); |
---|
| 293 | + |
---|
| 294 | + snprintf(tc_string, 8, "PTP "); |
---|
| 295 | + |
---|
| 296 | + for (i = 0; i < max(rx_ring_cnt, tx_ring_cnt); i++) { |
---|
| 297 | + for (si = 0; si < rx_stat_cnt; si++) { |
---|
| 298 | + snprintf(p, ETH_GSTRING_LEN, |
---|
| 299 | + aq_ethtool_queue_rx_stat_names[si], |
---|
| 300 | + tc_string, |
---|
| 301 | + i ? PTP_HWST_RING_IDX : ptp_ring_idx); |
---|
| 302 | + p += ETH_GSTRING_LEN; |
---|
| 303 | + } |
---|
| 304 | + if (i >= tx_ring_cnt) |
---|
| 305 | + continue; |
---|
| 306 | + for (si = 0; si < tx_stat_cnt; si++) { |
---|
| 307 | + snprintf(p, ETH_GSTRING_LEN, |
---|
| 308 | + aq_ethtool_queue_tx_stat_names[si], |
---|
| 309 | + tc_string, |
---|
| 310 | + i ? PTP_HWST_RING_IDX : ptp_ring_idx); |
---|
| 311 | + p += ETH_GSTRING_LEN; |
---|
| 312 | + } |
---|
| 313 | + } |
---|
| 314 | + } |
---|
| 315 | +#endif |
---|
| 316 | +#if IS_ENABLED(CONFIG_MACSEC) |
---|
| 317 | + if (!nic->macsec_cfg) |
---|
| 318 | + break; |
---|
| 319 | + |
---|
| 320 | + memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names)); |
---|
| 321 | + p = p + sizeof(aq_macsec_stat_names); |
---|
| 322 | + for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { |
---|
| 323 | + struct aq_macsec_txsc *aq_txsc; |
---|
| 324 | + |
---|
| 325 | + if (!(test_bit(i, &nic->macsec_cfg->txsc_idx_busy))) |
---|
| 326 | + continue; |
---|
| 327 | + |
---|
| 328 | + for (si = 0; |
---|
| 329 | + si < ARRAY_SIZE(aq_macsec_txsc_stat_names); |
---|
| 330 | + si++) { |
---|
| 331 | + snprintf(p, ETH_GSTRING_LEN, |
---|
| 332 | + aq_macsec_txsc_stat_names[si], i); |
---|
| 333 | + p += ETH_GSTRING_LEN; |
---|
| 334 | + } |
---|
| 335 | + aq_txsc = &nic->macsec_cfg->aq_txsc[i]; |
---|
| 336 | + for (sa = 0; sa < MACSEC_NUM_AN; sa++) { |
---|
| 337 | + if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy))) |
---|
| 338 | + continue; |
---|
| 339 | + for (si = 0; |
---|
| 340 | + si < ARRAY_SIZE(aq_macsec_txsa_stat_names); |
---|
| 341 | + si++) { |
---|
| 342 | + snprintf(p, ETH_GSTRING_LEN, |
---|
| 343 | + aq_macsec_txsa_stat_names[si], |
---|
| 344 | + i, sa); |
---|
| 345 | + p += ETH_GSTRING_LEN; |
---|
| 346 | + } |
---|
| 347 | + } |
---|
| 348 | + } |
---|
| 349 | + for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { |
---|
| 350 | + struct aq_macsec_rxsc *aq_rxsc; |
---|
| 351 | + |
---|
| 352 | + if (!(test_bit(i, &nic->macsec_cfg->rxsc_idx_busy))) |
---|
| 353 | + continue; |
---|
| 354 | + |
---|
| 355 | + aq_rxsc = &nic->macsec_cfg->aq_rxsc[i]; |
---|
| 356 | + for (sa = 0; sa < MACSEC_NUM_AN; sa++) { |
---|
| 357 | + if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy))) |
---|
| 358 | + continue; |
---|
| 359 | + for (si = 0; |
---|
| 360 | + si < ARRAY_SIZE(aq_macsec_rxsa_stat_names); |
---|
| 361 | + si++) { |
---|
| 362 | + snprintf(p, ETH_GSTRING_LEN, |
---|
| 363 | + aq_macsec_rxsa_stat_names[si], |
---|
| 364 | + i, sa); |
---|
| 365 | + p += ETH_GSTRING_LEN; |
---|
| 366 | + } |
---|
| 367 | + } |
---|
| 368 | + } |
---|
| 369 | +#endif |
---|
| 370 | + break; |
---|
152 | 371 | } |
---|
| 372 | + case ETH_SS_PRIV_FLAGS: |
---|
| 373 | + memcpy(p, aq_ethtool_priv_flag_names, |
---|
| 374 | + sizeof(aq_ethtool_priv_flag_names)); |
---|
| 375 | + break; |
---|
| 376 | + } |
---|
| 377 | +} |
---|
| 378 | + |
---|
| 379 | +static int aq_ethtool_set_phys_id(struct net_device *ndev, |
---|
| 380 | + enum ethtool_phys_id_state state) |
---|
| 381 | +{ |
---|
| 382 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 383 | + struct aq_hw_s *hw = aq_nic->aq_hw; |
---|
| 384 | + int ret = 0; |
---|
| 385 | + |
---|
| 386 | + if (!aq_nic->aq_fw_ops->led_control) |
---|
| 387 | + return -EOPNOTSUPP; |
---|
| 388 | + |
---|
| 389 | + mutex_lock(&aq_nic->fwreq_mutex); |
---|
| 390 | + |
---|
| 391 | + switch (state) { |
---|
| 392 | + case ETHTOOL_ID_ACTIVE: |
---|
| 393 | + ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_BLINK | |
---|
| 394 | + AQ_HW_LED_BLINK << 2 | AQ_HW_LED_BLINK << 4); |
---|
| 395 | + break; |
---|
| 396 | + case ETHTOOL_ID_INACTIVE: |
---|
| 397 | + ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_DEFAULT); |
---|
| 398 | + break; |
---|
| 399 | + default: |
---|
| 400 | + break; |
---|
| 401 | + } |
---|
| 402 | + |
---|
| 403 | + mutex_unlock(&aq_nic->fwreq_mutex); |
---|
| 404 | + |
---|
| 405 | + return ret; |
---|
153 | 406 | } |
---|
154 | 407 | |
---|
155 | 408 | static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset) |
---|
156 | 409 | { |
---|
157 | 410 | int ret = 0; |
---|
158 | | - struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
159 | | - struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); |
---|
160 | 411 | |
---|
161 | 412 | switch (stringset) { |
---|
162 | 413 | case ETH_SS_STATS: |
---|
163 | | - ret = ARRAY_SIZE(aq_ethtool_stat_names) + |
---|
164 | | - cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); |
---|
| 414 | + ret = aq_ethtool_n_stats(ndev); |
---|
| 415 | + break; |
---|
| 416 | + case ETH_SS_PRIV_FLAGS: |
---|
| 417 | + ret = ARRAY_SIZE(aq_ethtool_priv_flag_names); |
---|
165 | 418 | break; |
---|
166 | 419 | default: |
---|
167 | 420 | ret = -EOPNOTSUPP; |
---|
168 | 421 | } |
---|
| 422 | + |
---|
169 | 423 | return ret; |
---|
170 | 424 | } |
---|
171 | 425 | |
---|
.. | .. |
---|
177 | 431 | static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev) |
---|
178 | 432 | { |
---|
179 | 433 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
180 | | - struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); |
---|
| 434 | + struct aq_nic_cfg_s *cfg; |
---|
| 435 | + |
---|
| 436 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
181 | 437 | |
---|
182 | 438 | return sizeof(cfg->aq_rss.hash_secret_key); |
---|
183 | 439 | } |
---|
.. | .. |
---|
186 | 442 | u8 *hfunc) |
---|
187 | 443 | { |
---|
188 | 444 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
189 | | - struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); |
---|
| 445 | + struct aq_nic_cfg_s *cfg; |
---|
190 | 446 | unsigned int i = 0U; |
---|
| 447 | + |
---|
| 448 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
191 | 449 | |
---|
192 | 450 | if (hfunc) |
---|
193 | 451 | *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */ |
---|
.. | .. |
---|
198 | 456 | if (key) |
---|
199 | 457 | memcpy(key, cfg->aq_rss.hash_secret_key, |
---|
200 | 458 | sizeof(cfg->aq_rss.hash_secret_key)); |
---|
| 459 | + |
---|
201 | 460 | return 0; |
---|
| 461 | +} |
---|
| 462 | + |
---|
| 463 | +static int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir, |
---|
| 464 | + const u8 *key, const u8 hfunc) |
---|
| 465 | +{ |
---|
| 466 | + struct aq_nic_s *aq_nic = netdev_priv(netdev); |
---|
| 467 | + struct aq_nic_cfg_s *cfg; |
---|
| 468 | + unsigned int i = 0U; |
---|
| 469 | + u32 rss_entries; |
---|
| 470 | + int err = 0; |
---|
| 471 | + |
---|
| 472 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
| 473 | + rss_entries = cfg->aq_rss.indirection_table_size; |
---|
| 474 | + |
---|
| 475 | + /* We do not allow change in unsupported parameters */ |
---|
| 476 | + if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) |
---|
| 477 | + return -EOPNOTSUPP; |
---|
| 478 | + /* Fill out the redirection table */ |
---|
| 479 | + if (indir) |
---|
| 480 | + for (i = 0; i < rss_entries; i++) |
---|
| 481 | + cfg->aq_rss.indirection_table[i] = indir[i]; |
---|
| 482 | + |
---|
| 483 | + /* Fill out the rss hash key */ |
---|
| 484 | + if (key) { |
---|
| 485 | + memcpy(cfg->aq_rss.hash_secret_key, key, |
---|
| 486 | + sizeof(cfg->aq_rss.hash_secret_key)); |
---|
| 487 | + err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw, |
---|
| 488 | + &cfg->aq_rss); |
---|
| 489 | + if (err) |
---|
| 490 | + return err; |
---|
| 491 | + } |
---|
| 492 | + |
---|
| 493 | + err = aq_nic->aq_hw_ops->hw_rss_set(aq_nic->aq_hw, &cfg->aq_rss); |
---|
| 494 | + |
---|
| 495 | + return err; |
---|
202 | 496 | } |
---|
203 | 497 | |
---|
204 | 498 | static int aq_ethtool_get_rxnfc(struct net_device *ndev, |
---|
.. | .. |
---|
206 | 500 | u32 *rule_locs) |
---|
207 | 501 | { |
---|
208 | 502 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
209 | | - struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); |
---|
| 503 | + struct aq_nic_cfg_s *cfg; |
---|
210 | 504 | int err = 0; |
---|
| 505 | + |
---|
| 506 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
211 | 507 | |
---|
212 | 508 | switch (cmd->cmd) { |
---|
213 | 509 | case ETHTOOL_GRXRINGS: |
---|
214 | 510 | cmd->data = cfg->vecs; |
---|
215 | 511 | break; |
---|
| 512 | + case ETHTOOL_GRXCLSRLCNT: |
---|
| 513 | + cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic); |
---|
| 514 | + break; |
---|
| 515 | + case ETHTOOL_GRXCLSRULE: |
---|
| 516 | + err = aq_get_rxnfc_rule(aq_nic, cmd); |
---|
| 517 | + break; |
---|
| 518 | + case ETHTOOL_GRXCLSRLALL: |
---|
| 519 | + err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs); |
---|
| 520 | + break; |
---|
| 521 | + default: |
---|
| 522 | + err = -EOPNOTSUPP; |
---|
| 523 | + break; |
---|
| 524 | + } |
---|
216 | 525 | |
---|
| 526 | + return err; |
---|
| 527 | +} |
---|
| 528 | + |
---|
| 529 | +static int aq_ethtool_set_rxnfc(struct net_device *ndev, |
---|
| 530 | + struct ethtool_rxnfc *cmd) |
---|
| 531 | +{ |
---|
| 532 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 533 | + int err = 0; |
---|
| 534 | + |
---|
| 535 | + switch (cmd->cmd) { |
---|
| 536 | + case ETHTOOL_SRXCLSRLINS: |
---|
| 537 | + err = aq_add_rxnfc_rule(aq_nic, cmd); |
---|
| 538 | + break; |
---|
| 539 | + case ETHTOOL_SRXCLSRLDEL: |
---|
| 540 | + err = aq_del_rxnfc_rule(aq_nic, cmd); |
---|
| 541 | + break; |
---|
217 | 542 | default: |
---|
218 | 543 | err = -EOPNOTSUPP; |
---|
219 | 544 | break; |
---|
.. | .. |
---|
226 | 551 | struct ethtool_coalesce *coal) |
---|
227 | 552 | { |
---|
228 | 553 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
229 | | - struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); |
---|
| 554 | + struct aq_nic_cfg_s *cfg; |
---|
| 555 | + |
---|
| 556 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
230 | 557 | |
---|
231 | 558 | if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON || |
---|
232 | 559 | cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) { |
---|
.. | .. |
---|
240 | 567 | coal->rx_max_coalesced_frames = 1; |
---|
241 | 568 | coal->tx_max_coalesced_frames = 1; |
---|
242 | 569 | } |
---|
| 570 | + |
---|
243 | 571 | return 0; |
---|
244 | 572 | } |
---|
245 | 573 | |
---|
.. | .. |
---|
247 | 575 | struct ethtool_coalesce *coal) |
---|
248 | 576 | { |
---|
249 | 577 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
250 | | - struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); |
---|
| 578 | + struct aq_nic_cfg_s *cfg; |
---|
251 | 579 | |
---|
252 | | - /* This is not yet supported |
---|
253 | | - */ |
---|
254 | | - if (coal->use_adaptive_rx_coalesce || coal->use_adaptive_tx_coalesce) |
---|
255 | | - return -EOPNOTSUPP; |
---|
| 580 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
256 | 581 | |
---|
257 | 582 | /* Atlantic only supports timing based coalescing |
---|
258 | 583 | */ |
---|
259 | 584 | if (coal->rx_max_coalesced_frames > 1 || |
---|
260 | | - coal->rx_coalesce_usecs_irq || |
---|
261 | | - coal->rx_max_coalesced_frames_irq) |
---|
262 | | - return -EOPNOTSUPP; |
---|
263 | | - |
---|
264 | | - if (coal->tx_max_coalesced_frames > 1 || |
---|
265 | | - coal->tx_coalesce_usecs_irq || |
---|
266 | | - coal->tx_max_coalesced_frames_irq) |
---|
| 585 | + coal->tx_max_coalesced_frames > 1) |
---|
267 | 586 | return -EOPNOTSUPP; |
---|
268 | 587 | |
---|
269 | 588 | /* We do not support frame counting. Check this |
---|
.. | .. |
---|
285 | 604 | return aq_nic_update_interrupt_moderation_settings(aq_nic); |
---|
286 | 605 | } |
---|
287 | 606 | |
---|
| 607 | +static void aq_ethtool_get_wol(struct net_device *ndev, |
---|
| 608 | + struct ethtool_wolinfo *wol) |
---|
| 609 | +{ |
---|
| 610 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 611 | + struct aq_nic_cfg_s *cfg; |
---|
| 612 | + |
---|
| 613 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
| 614 | + |
---|
| 615 | + wol->supported = AQ_NIC_WOL_MODES; |
---|
| 616 | + wol->wolopts = cfg->wol; |
---|
| 617 | +} |
---|
| 618 | + |
---|
| 619 | +static int aq_ethtool_set_wol(struct net_device *ndev, |
---|
| 620 | + struct ethtool_wolinfo *wol) |
---|
| 621 | +{ |
---|
| 622 | + struct pci_dev *pdev = to_pci_dev(ndev->dev.parent); |
---|
| 623 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 624 | + struct aq_nic_cfg_s *cfg; |
---|
| 625 | + int err = 0; |
---|
| 626 | + |
---|
| 627 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
| 628 | + |
---|
| 629 | + if (wol->wolopts & ~AQ_NIC_WOL_MODES) |
---|
| 630 | + return -EOPNOTSUPP; |
---|
| 631 | + |
---|
| 632 | + cfg->wol = wol->wolopts; |
---|
| 633 | + |
---|
| 634 | + err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol); |
---|
| 635 | + |
---|
| 636 | + return err; |
---|
| 637 | +} |
---|
| 638 | + |
---|
| 639 | +static int aq_ethtool_get_ts_info(struct net_device *ndev, |
---|
| 640 | + struct ethtool_ts_info *info) |
---|
| 641 | +{ |
---|
| 642 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 643 | + |
---|
| 644 | + ethtool_op_get_ts_info(ndev, info); |
---|
| 645 | + |
---|
| 646 | + if (!aq_nic->aq_ptp) |
---|
| 647 | + return 0; |
---|
| 648 | + |
---|
| 649 | + info->so_timestamping |= |
---|
| 650 | + SOF_TIMESTAMPING_TX_HARDWARE | |
---|
| 651 | + SOF_TIMESTAMPING_RX_HARDWARE | |
---|
| 652 | + SOF_TIMESTAMPING_RAW_HARDWARE; |
---|
| 653 | + |
---|
| 654 | + info->tx_types = BIT(HWTSTAMP_TX_OFF) | |
---|
| 655 | + BIT(HWTSTAMP_TX_ON); |
---|
| 656 | + |
---|
| 657 | + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); |
---|
| 658 | + |
---|
| 659 | + info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | |
---|
| 660 | + BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | |
---|
| 661 | + BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); |
---|
| 662 | + |
---|
| 663 | +#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) |
---|
| 664 | + info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp)); |
---|
| 665 | +#endif |
---|
| 666 | + |
---|
| 667 | + return 0; |
---|
| 668 | +} |
---|
| 669 | + |
---|
| 670 | +static u32 eee_mask_to_ethtool_mask(u32 speed) |
---|
| 671 | +{ |
---|
| 672 | + u32 rate = 0; |
---|
| 673 | + |
---|
| 674 | + if (speed & AQ_NIC_RATE_EEE_10G) |
---|
| 675 | + rate |= SUPPORTED_10000baseT_Full; |
---|
| 676 | + |
---|
| 677 | + if (speed & AQ_NIC_RATE_EEE_1G) |
---|
| 678 | + rate |= SUPPORTED_1000baseT_Full; |
---|
| 679 | + |
---|
| 680 | + if (speed & AQ_NIC_RATE_EEE_100M) |
---|
| 681 | + rate |= SUPPORTED_100baseT_Full; |
---|
| 682 | + |
---|
| 683 | + return rate; |
---|
| 684 | +} |
---|
| 685 | + |
---|
| 686 | +static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee) |
---|
| 687 | +{ |
---|
| 688 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 689 | + u32 rate, supported_rates; |
---|
| 690 | + int err = 0; |
---|
| 691 | + |
---|
| 692 | + if (!aq_nic->aq_fw_ops->get_eee_rate) |
---|
| 693 | + return -EOPNOTSUPP; |
---|
| 694 | + |
---|
| 695 | + mutex_lock(&aq_nic->fwreq_mutex); |
---|
| 696 | + err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate, |
---|
| 697 | + &supported_rates); |
---|
| 698 | + mutex_unlock(&aq_nic->fwreq_mutex); |
---|
| 699 | + if (err < 0) |
---|
| 700 | + return err; |
---|
| 701 | + |
---|
| 702 | + eee->supported = eee_mask_to_ethtool_mask(supported_rates); |
---|
| 703 | + |
---|
| 704 | + if (aq_nic->aq_nic_cfg.eee_speeds) |
---|
| 705 | + eee->advertised = eee->supported; |
---|
| 706 | + |
---|
| 707 | + eee->lp_advertised = eee_mask_to_ethtool_mask(rate); |
---|
| 708 | + |
---|
| 709 | + eee->eee_enabled = !!eee->advertised; |
---|
| 710 | + |
---|
| 711 | + eee->tx_lpi_enabled = eee->eee_enabled; |
---|
| 712 | + if ((supported_rates & rate) & AQ_NIC_RATE_EEE_MSK) |
---|
| 713 | + eee->eee_active = true; |
---|
| 714 | + |
---|
| 715 | + return 0; |
---|
| 716 | +} |
---|
| 717 | + |
---|
| 718 | +static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee) |
---|
| 719 | +{ |
---|
| 720 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 721 | + u32 rate, supported_rates; |
---|
| 722 | + struct aq_nic_cfg_s *cfg; |
---|
| 723 | + int err = 0; |
---|
| 724 | + |
---|
| 725 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
| 726 | + |
---|
| 727 | + if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate || |
---|
| 728 | + !aq_nic->aq_fw_ops->set_eee_rate)) |
---|
| 729 | + return -EOPNOTSUPP; |
---|
| 730 | + |
---|
| 731 | + mutex_lock(&aq_nic->fwreq_mutex); |
---|
| 732 | + err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate, |
---|
| 733 | + &supported_rates); |
---|
| 734 | + mutex_unlock(&aq_nic->fwreq_mutex); |
---|
| 735 | + if (err < 0) |
---|
| 736 | + return err; |
---|
| 737 | + |
---|
| 738 | + if (eee->eee_enabled) { |
---|
| 739 | + rate = supported_rates; |
---|
| 740 | + cfg->eee_speeds = rate; |
---|
| 741 | + } else { |
---|
| 742 | + rate = 0; |
---|
| 743 | + cfg->eee_speeds = 0; |
---|
| 744 | + } |
---|
| 745 | + |
---|
| 746 | + mutex_lock(&aq_nic->fwreq_mutex); |
---|
| 747 | + err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate); |
---|
| 748 | + mutex_unlock(&aq_nic->fwreq_mutex); |
---|
| 749 | + |
---|
| 750 | + return err; |
---|
| 751 | +} |
---|
| 752 | + |
---|
288 | 753 | static int aq_ethtool_nway_reset(struct net_device *ndev) |
---|
289 | 754 | { |
---|
290 | 755 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 756 | + int err = 0; |
---|
291 | 757 | |
---|
292 | 758 | if (unlikely(!aq_nic->aq_fw_ops->renegotiate)) |
---|
293 | 759 | return -EOPNOTSUPP; |
---|
294 | 760 | |
---|
295 | | - if (netif_running(ndev)) |
---|
296 | | - return aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw); |
---|
| 761 | + if (netif_running(ndev)) { |
---|
| 762 | + mutex_lock(&aq_nic->fwreq_mutex); |
---|
| 763 | + err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw); |
---|
| 764 | + mutex_unlock(&aq_nic->fwreq_mutex); |
---|
| 765 | + } |
---|
297 | 766 | |
---|
298 | | - return 0; |
---|
| 767 | + return err; |
---|
299 | 768 | } |
---|
300 | 769 | |
---|
301 | 770 | static void aq_ethtool_get_pauseparam(struct net_device *ndev, |
---|
302 | 771 | struct ethtool_pauseparam *pause) |
---|
303 | 772 | { |
---|
304 | 773 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 774 | + int fc = aq_nic->aq_nic_cfg.fc.req; |
---|
305 | 775 | |
---|
306 | 776 | pause->autoneg = 0; |
---|
307 | 777 | |
---|
308 | | - if (aq_nic->aq_hw->aq_nic_cfg->flow_control & AQ_NIC_FC_RX) |
---|
309 | | - pause->rx_pause = 1; |
---|
310 | | - if (aq_nic->aq_hw->aq_nic_cfg->flow_control & AQ_NIC_FC_TX) |
---|
311 | | - pause->tx_pause = 1; |
---|
| 778 | + pause->rx_pause = !!(fc & AQ_NIC_FC_RX); |
---|
| 779 | + pause->tx_pause = !!(fc & AQ_NIC_FC_TX); |
---|
312 | 780 | } |
---|
313 | 781 | |
---|
314 | 782 | static int aq_ethtool_set_pauseparam(struct net_device *ndev, |
---|
.. | .. |
---|
324 | 792 | return -EOPNOTSUPP; |
---|
325 | 793 | |
---|
326 | 794 | if (pause->rx_pause) |
---|
327 | | - aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_RX; |
---|
| 795 | + aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX; |
---|
328 | 796 | else |
---|
329 | | - aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_RX; |
---|
| 797 | + aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX; |
---|
330 | 798 | |
---|
331 | 799 | if (pause->tx_pause) |
---|
332 | | - aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_TX; |
---|
| 800 | + aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX; |
---|
333 | 801 | else |
---|
334 | | - aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX; |
---|
| 802 | + aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX; |
---|
335 | 803 | |
---|
| 804 | + mutex_lock(&aq_nic->fwreq_mutex); |
---|
336 | 805 | err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw); |
---|
| 806 | + mutex_unlock(&aq_nic->fwreq_mutex); |
---|
337 | 807 | |
---|
338 | 808 | return err; |
---|
339 | 809 | } |
---|
.. | .. |
---|
342 | 812 | struct ethtool_ringparam *ring) |
---|
343 | 813 | { |
---|
344 | 814 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
345 | | - struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic); |
---|
| 815 | + struct aq_nic_cfg_s *cfg; |
---|
346 | 816 | |
---|
347 | | - ring->rx_pending = aq_nic_cfg->rxds; |
---|
348 | | - ring->tx_pending = aq_nic_cfg->txds; |
---|
| 817 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
349 | 818 | |
---|
350 | | - ring->rx_max_pending = aq_nic_cfg->aq_hw_caps->rxds_max; |
---|
351 | | - ring->tx_max_pending = aq_nic_cfg->aq_hw_caps->txds_max; |
---|
| 819 | + ring->rx_pending = cfg->rxds; |
---|
| 820 | + ring->tx_pending = cfg->txds; |
---|
| 821 | + |
---|
| 822 | + ring->rx_max_pending = cfg->aq_hw_caps->rxds_max; |
---|
| 823 | + ring->tx_max_pending = cfg->aq_hw_caps->txds_max; |
---|
352 | 824 | } |
---|
353 | 825 | |
---|
354 | 826 | static int aq_set_ringparam(struct net_device *ndev, |
---|
355 | 827 | struct ethtool_ringparam *ring) |
---|
356 | 828 | { |
---|
357 | | - int err = 0; |
---|
358 | | - bool ndev_running = false; |
---|
359 | 829 | struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
360 | | - struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic); |
---|
361 | | - const struct aq_hw_caps_s *hw_caps = aq_nic_cfg->aq_hw_caps; |
---|
| 830 | + const struct aq_hw_caps_s *hw_caps; |
---|
| 831 | + bool ndev_running = false; |
---|
| 832 | + struct aq_nic_cfg_s *cfg; |
---|
| 833 | + int err = 0; |
---|
| 834 | + |
---|
| 835 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
| 836 | + hw_caps = cfg->aq_hw_caps; |
---|
362 | 837 | |
---|
363 | 838 | if (ring->rx_mini_pending || ring->rx_jumbo_pending) { |
---|
364 | 839 | err = -EOPNOTSUPP; |
---|
.. | .. |
---|
367 | 842 | |
---|
368 | 843 | if (netif_running(ndev)) { |
---|
369 | 844 | ndev_running = true; |
---|
370 | | - dev_close(ndev); |
---|
| 845 | + aq_ndev_close(ndev); |
---|
371 | 846 | } |
---|
372 | 847 | |
---|
373 | | - aq_nic_free_vectors(aq_nic); |
---|
| 848 | + cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min); |
---|
| 849 | + cfg->rxds = min(cfg->rxds, hw_caps->rxds_max); |
---|
| 850 | + cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE); |
---|
374 | 851 | |
---|
375 | | - aq_nic_cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min); |
---|
376 | | - aq_nic_cfg->rxds = min(aq_nic_cfg->rxds, hw_caps->rxds_max); |
---|
377 | | - aq_nic_cfg->rxds = ALIGN(aq_nic_cfg->rxds, AQ_HW_RXD_MULTIPLE); |
---|
| 852 | + cfg->txds = max(ring->tx_pending, hw_caps->txds_min); |
---|
| 853 | + cfg->txds = min(cfg->txds, hw_caps->txds_max); |
---|
| 854 | + cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE); |
---|
378 | 855 | |
---|
379 | | - aq_nic_cfg->txds = max(ring->tx_pending, hw_caps->txds_min); |
---|
380 | | - aq_nic_cfg->txds = min(aq_nic_cfg->txds, hw_caps->txds_max); |
---|
381 | | - aq_nic_cfg->txds = ALIGN(aq_nic_cfg->txds, AQ_HW_TXD_MULTIPLE); |
---|
| 856 | + err = aq_nic_realloc_vectors(aq_nic); |
---|
| 857 | + if (err) |
---|
| 858 | + goto err_exit; |
---|
382 | 859 | |
---|
383 | | - for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < aq_nic_cfg->vecs; |
---|
384 | | - aq_nic->aq_vecs++) { |
---|
385 | | - aq_nic->aq_vec[aq_nic->aq_vecs] = |
---|
386 | | - aq_vec_alloc(aq_nic, aq_nic->aq_vecs, aq_nic_cfg); |
---|
387 | | - if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) { |
---|
388 | | - err = -ENOMEM; |
---|
389 | | - goto err_exit; |
---|
390 | | - } |
---|
391 | | - } |
---|
392 | 860 | if (ndev_running) |
---|
393 | | - err = dev_open(ndev); |
---|
| 861 | + err = aq_ndev_open(ndev); |
---|
394 | 862 | |
---|
395 | 863 | err_exit: |
---|
396 | 864 | return err; |
---|
397 | 865 | } |
---|
398 | 866 | |
---|
| 867 | +static u32 aq_get_msg_level(struct net_device *ndev) |
---|
| 868 | +{ |
---|
| 869 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 870 | + |
---|
| 871 | + return aq_nic->msg_enable; |
---|
| 872 | +} |
---|
| 873 | + |
---|
| 874 | +static void aq_set_msg_level(struct net_device *ndev, u32 data) |
---|
| 875 | +{ |
---|
| 876 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 877 | + |
---|
| 878 | + aq_nic->msg_enable = data; |
---|
| 879 | +} |
---|
| 880 | + |
---|
| 881 | +static u32 aq_ethtool_get_priv_flags(struct net_device *ndev) |
---|
| 882 | +{ |
---|
| 883 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 884 | + |
---|
| 885 | + return aq_nic->aq_nic_cfg.priv_flags; |
---|
| 886 | +} |
---|
| 887 | + |
---|
| 888 | +static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags) |
---|
| 889 | +{ |
---|
| 890 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 891 | + struct aq_nic_cfg_s *cfg; |
---|
| 892 | + u32 priv_flags; |
---|
| 893 | + int ret = 0; |
---|
| 894 | + |
---|
| 895 | + cfg = aq_nic_get_cfg(aq_nic); |
---|
| 896 | + priv_flags = cfg->priv_flags; |
---|
| 897 | + |
---|
| 898 | + if (flags & ~AQ_PRIV_FLAGS_MASK) |
---|
| 899 | + return -EOPNOTSUPP; |
---|
| 900 | + |
---|
| 901 | + if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) { |
---|
| 902 | + netdev_info(ndev, "Can't enable more than one loopback simultaneously\n"); |
---|
| 903 | + return -EINVAL; |
---|
| 904 | + } |
---|
| 905 | + |
---|
| 906 | + cfg->priv_flags = flags; |
---|
| 907 | + |
---|
| 908 | + if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) { |
---|
| 909 | + if (netif_running(ndev)) { |
---|
| 910 | + dev_close(ndev); |
---|
| 911 | + |
---|
| 912 | + dev_open(ndev, NULL); |
---|
| 913 | + } |
---|
| 914 | + } else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) { |
---|
| 915 | + ret = aq_nic_set_loopback(aq_nic); |
---|
| 916 | + } |
---|
| 917 | + |
---|
| 918 | + return ret; |
---|
| 919 | +} |
---|
| 920 | + |
---|
| 921 | +static int aq_ethtool_get_phy_tunable(struct net_device *ndev, |
---|
| 922 | + const struct ethtool_tunable *tuna, void *data) |
---|
| 923 | +{ |
---|
| 924 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 925 | + |
---|
| 926 | + switch (tuna->id) { |
---|
| 927 | + case ETHTOOL_PHY_EDPD: { |
---|
| 928 | + u16 *val = data; |
---|
| 929 | + |
---|
| 930 | + *val = aq_nic->aq_nic_cfg.is_media_detect ? AQ_HW_MEDIA_DETECT_CNT : 0; |
---|
| 931 | + break; |
---|
| 932 | + } |
---|
| 933 | + case ETHTOOL_PHY_DOWNSHIFT: { |
---|
| 934 | + u8 *val = data; |
---|
| 935 | + |
---|
| 936 | + *val = (u8)aq_nic->aq_nic_cfg.downshift_counter; |
---|
| 937 | + break; |
---|
| 938 | + } |
---|
| 939 | + default: |
---|
| 940 | + return -EOPNOTSUPP; |
---|
| 941 | + } |
---|
| 942 | + |
---|
| 943 | + return 0; |
---|
| 944 | +} |
---|
| 945 | + |
---|
| 946 | +static int aq_ethtool_set_phy_tunable(struct net_device *ndev, |
---|
| 947 | + const struct ethtool_tunable *tuna, const void *data) |
---|
| 948 | +{ |
---|
| 949 | + int err = -EOPNOTSUPP; |
---|
| 950 | + struct aq_nic_s *aq_nic = netdev_priv(ndev); |
---|
| 951 | + |
---|
| 952 | + switch (tuna->id) { |
---|
| 953 | + case ETHTOOL_PHY_EDPD: { |
---|
| 954 | + const u16 *val = data; |
---|
| 955 | + |
---|
| 956 | + err = aq_nic_set_media_detect(aq_nic, *val); |
---|
| 957 | + break; |
---|
| 958 | + } |
---|
| 959 | + case ETHTOOL_PHY_DOWNSHIFT: { |
---|
| 960 | + const u8 *val = data; |
---|
| 961 | + |
---|
| 962 | + err = aq_nic_set_downshift(aq_nic, *val); |
---|
| 963 | + break; |
---|
| 964 | + } |
---|
| 965 | + default: |
---|
| 966 | + break; |
---|
| 967 | + } |
---|
| 968 | + |
---|
| 969 | + return err; |
---|
| 970 | +} |
---|
| 971 | + |
---|
399 | 972 | const struct ethtool_ops aq_ethtool_ops = { |
---|
| 973 | + .supported_coalesce_params = ETHTOOL_COALESCE_USECS | |
---|
| 974 | + ETHTOOL_COALESCE_MAX_FRAMES, |
---|
400 | 975 | .get_link = aq_ethtool_get_link, |
---|
401 | 976 | .get_regs_len = aq_ethtool_get_regs_len, |
---|
402 | 977 | .get_regs = aq_ethtool_get_regs, |
---|
403 | 978 | .get_drvinfo = aq_ethtool_get_drvinfo, |
---|
404 | 979 | .get_strings = aq_ethtool_get_strings, |
---|
| 980 | + .set_phys_id = aq_ethtool_set_phys_id, |
---|
405 | 981 | .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size, |
---|
| 982 | + .get_wol = aq_ethtool_get_wol, |
---|
| 983 | + .set_wol = aq_ethtool_set_wol, |
---|
406 | 984 | .nway_reset = aq_ethtool_nway_reset, |
---|
407 | 985 | .get_ringparam = aq_get_ringparam, |
---|
408 | 986 | .set_ringparam = aq_set_ringparam, |
---|
| 987 | + .get_eee = aq_ethtool_get_eee, |
---|
| 988 | + .set_eee = aq_ethtool_set_eee, |
---|
409 | 989 | .get_pauseparam = aq_ethtool_get_pauseparam, |
---|
410 | 990 | .set_pauseparam = aq_ethtool_set_pauseparam, |
---|
411 | 991 | .get_rxfh_key_size = aq_ethtool_get_rss_key_size, |
---|
412 | 992 | .get_rxfh = aq_ethtool_get_rss, |
---|
| 993 | + .set_rxfh = aq_ethtool_set_rss, |
---|
413 | 994 | .get_rxnfc = aq_ethtool_get_rxnfc, |
---|
| 995 | + .set_rxnfc = aq_ethtool_set_rxnfc, |
---|
| 996 | + .get_msglevel = aq_get_msg_level, |
---|
| 997 | + .set_msglevel = aq_set_msg_level, |
---|
414 | 998 | .get_sset_count = aq_ethtool_get_sset_count, |
---|
415 | 999 | .get_ethtool_stats = aq_ethtool_stats, |
---|
| 1000 | + .get_priv_flags = aq_ethtool_get_priv_flags, |
---|
| 1001 | + .set_priv_flags = aq_ethtool_set_priv_flags, |
---|
416 | 1002 | .get_link_ksettings = aq_ethtool_get_link_ksettings, |
---|
417 | 1003 | .set_link_ksettings = aq_ethtool_set_link_ksettings, |
---|
418 | 1004 | .get_coalesce = aq_ethtool_get_coalesce, |
---|
419 | 1005 | .set_coalesce = aq_ethtool_set_coalesce, |
---|
| 1006 | + .get_ts_info = aq_ethtool_get_ts_info, |
---|
| 1007 | + .get_phy_tunable = aq_ethtool_get_phy_tunable, |
---|
| 1008 | + .set_phy_tunable = aq_ethtool_set_phy_tunable, |
---|
420 | 1009 | }; |
---|