1eb8ce9acSXue Chaojing // SPDX-License-Identifier: GPL-2.0
2eb8ce9acSXue Chaojing /* Huawei HiNIC PCI Express Linux driver
3eb8ce9acSXue Chaojing * Copyright(c) 2017 Huawei Technologies Co., Ltd
4eb8ce9acSXue Chaojing *
5eb8ce9acSXue Chaojing * This program is free software; you can redistribute it and/or modify it
6eb8ce9acSXue Chaojing * under the terms and conditions of the GNU General Public License,
7eb8ce9acSXue Chaojing * version 2, as published by the Free Software Foundation.
8eb8ce9acSXue Chaojing *
9eb8ce9acSXue Chaojing * This program is distributed in the hope it will be useful, but WITHOUT
10eb8ce9acSXue Chaojing * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11eb8ce9acSXue Chaojing * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12eb8ce9acSXue Chaojing * for more details.
13eb8ce9acSXue Chaojing *
14eb8ce9acSXue Chaojing */
15eb8ce9acSXue Chaojing
16eb8ce9acSXue Chaojing #include <linux/kernel.h>
17eb8ce9acSXue Chaojing #include <linux/pci.h>
18eb8ce9acSXue Chaojing #include <linux/device.h>
19eb8ce9acSXue Chaojing #include <linux/module.h>
20eb8ce9acSXue Chaojing #include <linux/types.h>
21eb8ce9acSXue Chaojing #include <linux/errno.h>
22eb8ce9acSXue Chaojing #include <linux/interrupt.h>
23eb8ce9acSXue Chaojing #include <linux/etherdevice.h>
24eb8ce9acSXue Chaojing #include <linux/netdevice.h>
25eb8ce9acSXue Chaojing #include <linux/if_vlan.h>
26eb8ce9acSXue Chaojing #include <linux/ethtool.h>
27eb8ce9acSXue Chaojing #include <linux/vmalloc.h>
282ac84cd1SLuo bin #include <linux/sfp.h>
29eb8ce9acSXue Chaojing
30eb8ce9acSXue Chaojing #include "hinic_hw_qp.h"
31eb8ce9acSXue Chaojing #include "hinic_hw_dev.h"
32eb8ce9acSXue Chaojing #include "hinic_port.h"
33eb8ce9acSXue Chaojing #include "hinic_tx.h"
34eb8ce9acSXue Chaojing #include "hinic_rx.h"
35eb8ce9acSXue Chaojing #include "hinic_dev.h"
36eb8ce9acSXue Chaojing
3784c7f6c3SArnd Bergmann #define SET_LINK_STR_MAX_LEN 16
3801f2b3daSLuo bin
3901f2b3daSLuo bin #define GET_SUPPORTED_MODE 0
4001f2b3daSLuo bin #define GET_ADVERTISED_MODE 1
4101f2b3daSLuo bin
4201f2b3daSLuo bin #define ETHTOOL_ADD_SUPPORTED_SPEED_LINK_MODE(ecmd, mode) \
4301f2b3daSLuo bin ((ecmd)->supported |= \
4401f2b3daSLuo bin (1UL << hw_to_ethtool_link_mode_table[mode].link_mode_bit))
4501f2b3daSLuo bin #define ETHTOOL_ADD_ADVERTISED_SPEED_LINK_MODE(ecmd, mode) \
4601f2b3daSLuo bin ((ecmd)->advertising |= \
4701f2b3daSLuo bin (1UL << hw_to_ethtool_link_mode_table[mode].link_mode_bit))
4801f2b3daSLuo bin #define ETHTOOL_ADD_SUPPORTED_LINK_MODE(ecmd, mode) \
4901f2b3daSLuo bin ((ecmd)->supported |= SUPPORTED_##mode)
5001f2b3daSLuo bin #define ETHTOOL_ADD_ADVERTISED_LINK_MODE(ecmd, mode) \
5101f2b3daSLuo bin ((ecmd)->advertising |= ADVERTISED_##mode)
5201f2b3daSLuo bin
53a0337c0dSLuo bin #define COALESCE_PENDING_LIMIT_UNIT 8
54a0337c0dSLuo bin #define COALESCE_TIMER_CFG_UNIT 9
55a0337c0dSLuo bin #define COALESCE_ALL_QUEUE 0xFFFF
56a0337c0dSLuo bin #define COALESCE_MAX_PENDING_LIMIT (255 * COALESCE_PENDING_LIMIT_UNIT)
57a0337c0dSLuo bin #define COALESCE_MAX_TIMER_CFG (255 * COALESCE_TIMER_CFG_UNIT)
58a0337c0dSLuo bin
5901f2b3daSLuo bin struct hw2ethtool_link_mode {
6001f2b3daSLuo bin enum ethtool_link_mode_bit_indices link_mode_bit;
6101f2b3daSLuo bin u32 speed;
6201f2b3daSLuo bin enum hinic_link_mode hw_link_mode;
6301f2b3daSLuo bin };
6401f2b3daSLuo bin
6501f2b3daSLuo bin struct cmd_link_settings {
6601f2b3daSLuo bin u64 supported;
6701f2b3daSLuo bin u64 advertising;
6801f2b3daSLuo bin
6901f2b3daSLuo bin u32 speed;
7001f2b3daSLuo bin u8 duplex;
7101f2b3daSLuo bin u8 port;
7201f2b3daSLuo bin u8 autoneg;
7301f2b3daSLuo bin };
7401f2b3daSLuo bin
7501f2b3daSLuo bin static u32 hw_to_ethtool_speed[LINK_SPEED_LEVELS] = {
7601f2b3daSLuo bin SPEED_10, SPEED_100,
7701f2b3daSLuo bin SPEED_1000, SPEED_10000,
7801f2b3daSLuo bin SPEED_25000, SPEED_40000,
7901f2b3daSLuo bin SPEED_100000
8001f2b3daSLuo bin };
8101f2b3daSLuo bin
8201f2b3daSLuo bin static struct hw2ethtool_link_mode
8301f2b3daSLuo bin hw_to_ethtool_link_mode_table[HINIC_LINK_MODE_NUMBERS] = {
8401f2b3daSLuo bin {
8501f2b3daSLuo bin .link_mode_bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
8601f2b3daSLuo bin .speed = SPEED_10000,
8701f2b3daSLuo bin .hw_link_mode = HINIC_10GE_BASE_KR,
8801f2b3daSLuo bin },
8901f2b3daSLuo bin {
9001f2b3daSLuo bin .link_mode_bit = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
9101f2b3daSLuo bin .speed = SPEED_40000,
9201f2b3daSLuo bin .hw_link_mode = HINIC_40GE_BASE_KR4,
9301f2b3daSLuo bin },
9401f2b3daSLuo bin {
9501f2b3daSLuo bin .link_mode_bit = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
9601f2b3daSLuo bin .speed = SPEED_40000,
9701f2b3daSLuo bin .hw_link_mode = HINIC_40GE_BASE_CR4,
9801f2b3daSLuo bin },
9901f2b3daSLuo bin {
10001f2b3daSLuo bin .link_mode_bit = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
10101f2b3daSLuo bin .speed = SPEED_100000,
10201f2b3daSLuo bin .hw_link_mode = HINIC_100GE_BASE_KR4,
10301f2b3daSLuo bin },
10401f2b3daSLuo bin {
10501f2b3daSLuo bin .link_mode_bit = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
10601f2b3daSLuo bin .speed = SPEED_100000,
10701f2b3daSLuo bin .hw_link_mode = HINIC_100GE_BASE_CR4,
10801f2b3daSLuo bin },
10901f2b3daSLuo bin {
11001f2b3daSLuo bin .link_mode_bit = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
11101f2b3daSLuo bin .speed = SPEED_25000,
11201f2b3daSLuo bin .hw_link_mode = HINIC_25GE_BASE_KR_S,
11301f2b3daSLuo bin },
11401f2b3daSLuo bin {
11501f2b3daSLuo bin .link_mode_bit = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
11601f2b3daSLuo bin .speed = SPEED_25000,
11701f2b3daSLuo bin .hw_link_mode = HINIC_25GE_BASE_CR_S,
11801f2b3daSLuo bin },
11901f2b3daSLuo bin {
12001f2b3daSLuo bin .link_mode_bit = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
12101f2b3daSLuo bin .speed = SPEED_25000,
12201f2b3daSLuo bin .hw_link_mode = HINIC_25GE_BASE_KR,
12301f2b3daSLuo bin },
12401f2b3daSLuo bin {
12501f2b3daSLuo bin .link_mode_bit = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
12601f2b3daSLuo bin .speed = SPEED_25000,
12701f2b3daSLuo bin .hw_link_mode = HINIC_25GE_BASE_CR,
12801f2b3daSLuo bin },
12901f2b3daSLuo bin {
13001f2b3daSLuo bin .link_mode_bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
13101f2b3daSLuo bin .speed = SPEED_1000,
13201f2b3daSLuo bin .hw_link_mode = HINIC_GE_BASE_KX,
13301f2b3daSLuo bin },
13401f2b3daSLuo bin };
13501f2b3daSLuo bin
1364aa218a4SLuo bin #define LP_DEFAULT_TIME 5 /* seconds */
1374aa218a4SLuo bin #define LP_PKT_LEN 1514
1384aa218a4SLuo bin
1394aa218a4SLuo bin #define PORT_DOWN_ERR_IDX 0
1404aa218a4SLuo bin enum diag_test_index {
1414aa218a4SLuo bin INTERNAL_LP_TEST = 0,
1424aa218a4SLuo bin EXTERNAL_LP_TEST = 1,
1434aa218a4SLuo bin DIAG_TEST_MAX = 2,
1444aa218a4SLuo bin };
1454aa218a4SLuo bin
set_link_speed(struct ethtool_link_ksettings * link_ksettings,enum hinic_speed speed)146eb8ce9acSXue Chaojing static void set_link_speed(struct ethtool_link_ksettings *link_ksettings,
147eb8ce9acSXue Chaojing enum hinic_speed speed)
148eb8ce9acSXue Chaojing {
149eb8ce9acSXue Chaojing switch (speed) {
150eb8ce9acSXue Chaojing case HINIC_SPEED_10MB_LINK:
151eb8ce9acSXue Chaojing link_ksettings->base.speed = SPEED_10;
152eb8ce9acSXue Chaojing break;
153eb8ce9acSXue Chaojing
154eb8ce9acSXue Chaojing case HINIC_SPEED_100MB_LINK:
155eb8ce9acSXue Chaojing link_ksettings->base.speed = SPEED_100;
156eb8ce9acSXue Chaojing break;
157eb8ce9acSXue Chaojing
158eb8ce9acSXue Chaojing case HINIC_SPEED_1000MB_LINK:
159eb8ce9acSXue Chaojing link_ksettings->base.speed = SPEED_1000;
160eb8ce9acSXue Chaojing break;
161eb8ce9acSXue Chaojing
162eb8ce9acSXue Chaojing case HINIC_SPEED_10GB_LINK:
163eb8ce9acSXue Chaojing link_ksettings->base.speed = SPEED_10000;
164eb8ce9acSXue Chaojing break;
165eb8ce9acSXue Chaojing
166eb8ce9acSXue Chaojing case HINIC_SPEED_25GB_LINK:
167eb8ce9acSXue Chaojing link_ksettings->base.speed = SPEED_25000;
168eb8ce9acSXue Chaojing break;
169eb8ce9acSXue Chaojing
170eb8ce9acSXue Chaojing case HINIC_SPEED_40GB_LINK:
171eb8ce9acSXue Chaojing link_ksettings->base.speed = SPEED_40000;
172eb8ce9acSXue Chaojing break;
173eb8ce9acSXue Chaojing
174eb8ce9acSXue Chaojing case HINIC_SPEED_100GB_LINK:
175eb8ce9acSXue Chaojing link_ksettings->base.speed = SPEED_100000;
176eb8ce9acSXue Chaojing break;
177eb8ce9acSXue Chaojing
178eb8ce9acSXue Chaojing default:
179eb8ce9acSXue Chaojing link_ksettings->base.speed = SPEED_UNKNOWN;
180eb8ce9acSXue Chaojing break;
181eb8ce9acSXue Chaojing }
182eb8ce9acSXue Chaojing }
183eb8ce9acSXue Chaojing
hinic_get_link_mode_index(enum hinic_link_mode link_mode)18401f2b3daSLuo bin static int hinic_get_link_mode_index(enum hinic_link_mode link_mode)
18501f2b3daSLuo bin {
18601f2b3daSLuo bin int i = 0;
18701f2b3daSLuo bin
18801f2b3daSLuo bin for (i = 0; i < HINIC_LINK_MODE_NUMBERS; i++) {
18901f2b3daSLuo bin if (link_mode == hw_to_ethtool_link_mode_table[i].hw_link_mode)
19001f2b3daSLuo bin break;
19101f2b3daSLuo bin }
19201f2b3daSLuo bin
19301f2b3daSLuo bin return i;
19401f2b3daSLuo bin }
19501f2b3daSLuo bin
hinic_add_ethtool_link_mode(struct cmd_link_settings * link_settings,enum hinic_link_mode hw_link_mode,u32 name)19601f2b3daSLuo bin static void hinic_add_ethtool_link_mode(struct cmd_link_settings *link_settings,
19701f2b3daSLuo bin enum hinic_link_mode hw_link_mode,
19801f2b3daSLuo bin u32 name)
19901f2b3daSLuo bin {
20001f2b3daSLuo bin enum hinic_link_mode link_mode;
20101f2b3daSLuo bin int idx = 0;
20201f2b3daSLuo bin
20301f2b3daSLuo bin for (link_mode = 0; link_mode < HINIC_LINK_MODE_NUMBERS; link_mode++) {
20401f2b3daSLuo bin if (hw_link_mode & ((u32)1 << link_mode)) {
20501f2b3daSLuo bin idx = hinic_get_link_mode_index(link_mode);
20601f2b3daSLuo bin if (idx >= HINIC_LINK_MODE_NUMBERS)
20701f2b3daSLuo bin continue;
20801f2b3daSLuo bin
20901f2b3daSLuo bin if (name == GET_SUPPORTED_MODE)
21001f2b3daSLuo bin ETHTOOL_ADD_SUPPORTED_SPEED_LINK_MODE
21101f2b3daSLuo bin (link_settings, idx);
21201f2b3daSLuo bin else
21301f2b3daSLuo bin ETHTOOL_ADD_ADVERTISED_SPEED_LINK_MODE
21401f2b3daSLuo bin (link_settings, idx);
21501f2b3daSLuo bin }
21601f2b3daSLuo bin }
21701f2b3daSLuo bin }
21801f2b3daSLuo bin
hinic_link_port_type(struct cmd_link_settings * link_settings,enum hinic_port_type port_type)21901f2b3daSLuo bin static void hinic_link_port_type(struct cmd_link_settings *link_settings,
22001f2b3daSLuo bin enum hinic_port_type port_type)
22101f2b3daSLuo bin {
22201f2b3daSLuo bin switch (port_type) {
22301f2b3daSLuo bin case HINIC_PORT_ELEC:
22401f2b3daSLuo bin case HINIC_PORT_TP:
22501f2b3daSLuo bin ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, TP);
22601f2b3daSLuo bin ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, TP);
22701f2b3daSLuo bin link_settings->port = PORT_TP;
22801f2b3daSLuo bin break;
22901f2b3daSLuo bin
23001f2b3daSLuo bin case HINIC_PORT_AOC:
23101f2b3daSLuo bin case HINIC_PORT_FIBRE:
23201f2b3daSLuo bin ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE);
23301f2b3daSLuo bin ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE);
23401f2b3daSLuo bin link_settings->port = PORT_FIBRE;
23501f2b3daSLuo bin break;
23601f2b3daSLuo bin
23701f2b3daSLuo bin case HINIC_PORT_COPPER:
23801f2b3daSLuo bin ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE);
23901f2b3daSLuo bin ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE);
24001f2b3daSLuo bin link_settings->port = PORT_DA;
24101f2b3daSLuo bin break;
24201f2b3daSLuo bin
24301f2b3daSLuo bin case HINIC_PORT_BACKPLANE:
24401f2b3daSLuo bin ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Backplane);
24501f2b3daSLuo bin ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Backplane);
24601f2b3daSLuo bin link_settings->port = PORT_NONE;
24701f2b3daSLuo bin break;
24801f2b3daSLuo bin
24901f2b3daSLuo bin default:
25001f2b3daSLuo bin link_settings->port = PORT_OTHER;
25101f2b3daSLuo bin break;
25201f2b3daSLuo bin }
25301f2b3daSLuo bin }
25401f2b3daSLuo bin
hinic_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * link_ksettings)255eb8ce9acSXue Chaojing static int hinic_get_link_ksettings(struct net_device *netdev,
256eb8ce9acSXue Chaojing struct ethtool_link_ksettings
257eb8ce9acSXue Chaojing *link_ksettings)
258eb8ce9acSXue Chaojing {
259eb8ce9acSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
26001f2b3daSLuo bin struct hinic_link_mode_cmd link_mode = { 0 };
26101f2b3daSLuo bin struct hinic_pause_config pause_info = { 0 };
26201f2b3daSLuo bin struct cmd_link_settings settings = { 0 };
263eb8ce9acSXue Chaojing enum hinic_port_link_state link_state;
264eb8ce9acSXue Chaojing struct hinic_port_cap port_cap;
265eb8ce9acSXue Chaojing int err;
266eb8ce9acSXue Chaojing
26701f2b3daSLuo bin ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
268eb8ce9acSXue Chaojing ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
269eb8ce9acSXue Chaojing
270eb8ce9acSXue Chaojing link_ksettings->base.speed = SPEED_UNKNOWN;
271eb8ce9acSXue Chaojing link_ksettings->base.autoneg = AUTONEG_DISABLE;
272eb8ce9acSXue Chaojing link_ksettings->base.duplex = DUPLEX_UNKNOWN;
273eb8ce9acSXue Chaojing
274eb8ce9acSXue Chaojing err = hinic_port_get_cap(nic_dev, &port_cap);
275eb8ce9acSXue Chaojing if (err)
276eb8ce9acSXue Chaojing return err;
277eb8ce9acSXue Chaojing
27801f2b3daSLuo bin hinic_link_port_type(&settings, port_cap.port_type);
27901f2b3daSLuo bin link_ksettings->base.port = settings.port;
28001f2b3daSLuo bin
281eb8ce9acSXue Chaojing err = hinic_port_link_state(nic_dev, &link_state);
282eb8ce9acSXue Chaojing if (err)
283eb8ce9acSXue Chaojing return err;
284eb8ce9acSXue Chaojing
28501f2b3daSLuo bin if (link_state == HINIC_LINK_STATE_UP) {
286eb8ce9acSXue Chaojing set_link_speed(link_ksettings, port_cap.speed);
28701f2b3daSLuo bin link_ksettings->base.duplex =
28801f2b3daSLuo bin (port_cap.duplex == HINIC_DUPLEX_FULL) ?
28901f2b3daSLuo bin DUPLEX_FULL : DUPLEX_HALF;
29001f2b3daSLuo bin }
291eb8ce9acSXue Chaojing
292eb8ce9acSXue Chaojing if (!!(port_cap.autoneg_cap & HINIC_AUTONEG_SUPPORTED))
293eb8ce9acSXue Chaojing ethtool_link_ksettings_add_link_mode(link_ksettings,
294eb8ce9acSXue Chaojing advertising, Autoneg);
295eb8ce9acSXue Chaojing
296eb8ce9acSXue Chaojing if (port_cap.autoneg_state == HINIC_AUTONEG_ACTIVE)
297eb8ce9acSXue Chaojing link_ksettings->base.autoneg = AUTONEG_ENABLE;
298eb8ce9acSXue Chaojing
29901f2b3daSLuo bin err = hinic_get_link_mode(nic_dev->hwdev, &link_mode);
30001f2b3daSLuo bin if (err || link_mode.supported == HINIC_SUPPORTED_UNKNOWN ||
30101f2b3daSLuo bin link_mode.advertised == HINIC_SUPPORTED_UNKNOWN)
30201f2b3daSLuo bin return -EIO;
30301f2b3daSLuo bin
30401f2b3daSLuo bin hinic_add_ethtool_link_mode(&settings, link_mode.supported,
30501f2b3daSLuo bin GET_SUPPORTED_MODE);
30601f2b3daSLuo bin hinic_add_ethtool_link_mode(&settings, link_mode.advertised,
30701f2b3daSLuo bin GET_ADVERTISED_MODE);
30801f2b3daSLuo bin
30901f2b3daSLuo bin if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) {
31001f2b3daSLuo bin err = hinic_get_hw_pause_info(nic_dev->hwdev, &pause_info);
31101f2b3daSLuo bin if (err)
31201f2b3daSLuo bin return err;
31301f2b3daSLuo bin ETHTOOL_ADD_SUPPORTED_LINK_MODE(&settings, Pause);
31401f2b3daSLuo bin if (pause_info.rx_pause && pause_info.tx_pause) {
31501f2b3daSLuo bin ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Pause);
31601f2b3daSLuo bin } else if (pause_info.tx_pause) {
31701f2b3daSLuo bin ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Asym_Pause);
31801f2b3daSLuo bin } else if (pause_info.rx_pause) {
31901f2b3daSLuo bin ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Pause);
32001f2b3daSLuo bin ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Asym_Pause);
32101f2b3daSLuo bin }
32201f2b3daSLuo bin }
32301f2b3daSLuo bin
3244973056cSSean Anderson linkmode_copy(link_ksettings->link_modes.supported,
3254973056cSSean Anderson (unsigned long *)&settings.supported);
3264973056cSSean Anderson linkmode_copy(link_ksettings->link_modes.advertising,
3274973056cSSean Anderson (unsigned long *)&settings.advertising);
32801f2b3daSLuo bin
329eb8ce9acSXue Chaojing return 0;
330eb8ce9acSXue Chaojing }
331eb8ce9acSXue Chaojing
hinic_ethtool_to_hw_speed_level(u32 speed)33201f2b3daSLuo bin static int hinic_ethtool_to_hw_speed_level(u32 speed)
33301f2b3daSLuo bin {
33401f2b3daSLuo bin int i;
33501f2b3daSLuo bin
33601f2b3daSLuo bin for (i = 0; i < LINK_SPEED_LEVELS; i++) {
33701f2b3daSLuo bin if (hw_to_ethtool_speed[i] == speed)
33801f2b3daSLuo bin break;
33901f2b3daSLuo bin }
34001f2b3daSLuo bin
34101f2b3daSLuo bin return i;
34201f2b3daSLuo bin }
34301f2b3daSLuo bin
hinic_is_support_speed(enum hinic_link_mode supported_link,u32 speed)34401f2b3daSLuo bin static bool hinic_is_support_speed(enum hinic_link_mode supported_link,
34501f2b3daSLuo bin u32 speed)
34601f2b3daSLuo bin {
34701f2b3daSLuo bin enum hinic_link_mode link_mode;
34801f2b3daSLuo bin int idx;
34901f2b3daSLuo bin
35001f2b3daSLuo bin for (link_mode = 0; link_mode < HINIC_LINK_MODE_NUMBERS; link_mode++) {
35101f2b3daSLuo bin if (!(supported_link & ((u32)1 << link_mode)))
35201f2b3daSLuo bin continue;
35301f2b3daSLuo bin
35401f2b3daSLuo bin idx = hinic_get_link_mode_index(link_mode);
35501f2b3daSLuo bin if (idx >= HINIC_LINK_MODE_NUMBERS)
35601f2b3daSLuo bin continue;
35701f2b3daSLuo bin
35801f2b3daSLuo bin if (hw_to_ethtool_link_mode_table[idx].speed == speed)
35901f2b3daSLuo bin return true;
36001f2b3daSLuo bin }
36101f2b3daSLuo bin
36201f2b3daSLuo bin return false;
36301f2b3daSLuo bin }
36401f2b3daSLuo bin
hinic_is_speed_legal(struct hinic_dev * nic_dev,u32 speed)36501f2b3daSLuo bin static bool hinic_is_speed_legal(struct hinic_dev *nic_dev, u32 speed)
36601f2b3daSLuo bin {
36701f2b3daSLuo bin struct hinic_link_mode_cmd link_mode = { 0 };
36801f2b3daSLuo bin struct net_device *netdev = nic_dev->netdev;
36901f2b3daSLuo bin enum nic_speed_level speed_level = 0;
37001f2b3daSLuo bin int err;
37101f2b3daSLuo bin
37201f2b3daSLuo bin err = hinic_get_link_mode(nic_dev->hwdev, &link_mode);
37301f2b3daSLuo bin if (err)
37401f2b3daSLuo bin return false;
37501f2b3daSLuo bin
37601f2b3daSLuo bin if (link_mode.supported == HINIC_SUPPORTED_UNKNOWN ||
37701f2b3daSLuo bin link_mode.advertised == HINIC_SUPPORTED_UNKNOWN)
37801f2b3daSLuo bin return false;
37901f2b3daSLuo bin
38001f2b3daSLuo bin speed_level = hinic_ethtool_to_hw_speed_level(speed);
38101f2b3daSLuo bin if (speed_level >= LINK_SPEED_LEVELS ||
38201f2b3daSLuo bin !hinic_is_support_speed(link_mode.supported, speed)) {
38301f2b3daSLuo bin netif_err(nic_dev, drv, netdev,
38401f2b3daSLuo bin "Unsupported speed: %d\n", speed);
38501f2b3daSLuo bin return false;
38601f2b3daSLuo bin }
38701f2b3daSLuo bin
38801f2b3daSLuo bin return true;
38901f2b3daSLuo bin }
39001f2b3daSLuo bin
get_link_settings_type(struct hinic_dev * nic_dev,u8 autoneg,u32 speed,u32 * set_settings)39101f2b3daSLuo bin static int get_link_settings_type(struct hinic_dev *nic_dev,
39201f2b3daSLuo bin u8 autoneg, u32 speed, u32 *set_settings)
39301f2b3daSLuo bin {
39401f2b3daSLuo bin struct hinic_port_cap port_cap = { 0 };
39501f2b3daSLuo bin int err;
39601f2b3daSLuo bin
39701f2b3daSLuo bin err = hinic_port_get_cap(nic_dev, &port_cap);
39801f2b3daSLuo bin if (err)
39901f2b3daSLuo bin return err;
40001f2b3daSLuo bin
40101f2b3daSLuo bin /* always set autonegotiation */
40201f2b3daSLuo bin if (port_cap.autoneg_cap)
40301f2b3daSLuo bin *set_settings |= HILINK_LINK_SET_AUTONEG;
40401f2b3daSLuo bin
40501f2b3daSLuo bin if (autoneg == AUTONEG_ENABLE) {
40601f2b3daSLuo bin if (!port_cap.autoneg_cap) {
40701f2b3daSLuo bin netif_err(nic_dev, drv, nic_dev->netdev, "Not support autoneg\n");
40801f2b3daSLuo bin return -EOPNOTSUPP;
40901f2b3daSLuo bin }
41001f2b3daSLuo bin } else if (speed != (u32)SPEED_UNKNOWN) {
41101f2b3daSLuo bin /* set speed only when autoneg is disabled */
41201f2b3daSLuo bin if (!hinic_is_speed_legal(nic_dev, speed))
41301f2b3daSLuo bin return -EINVAL;
41401f2b3daSLuo bin *set_settings |= HILINK_LINK_SET_SPEED;
41501f2b3daSLuo bin } else {
41601f2b3daSLuo bin netif_err(nic_dev, drv, nic_dev->netdev, "Need to set speed when autoneg is off\n");
41701f2b3daSLuo bin return -EOPNOTSUPP;
41801f2b3daSLuo bin }
41901f2b3daSLuo bin
42001f2b3daSLuo bin return 0;
42101f2b3daSLuo bin }
42201f2b3daSLuo bin
set_link_settings_separate_cmd(struct hinic_dev * nic_dev,u32 set_settings,u8 autoneg,u32 speed)42301f2b3daSLuo bin static int set_link_settings_separate_cmd(struct hinic_dev *nic_dev,
42401f2b3daSLuo bin u32 set_settings, u8 autoneg,
42501f2b3daSLuo bin u32 speed)
42601f2b3daSLuo bin {
42701f2b3daSLuo bin enum nic_speed_level speed_level = 0;
42801f2b3daSLuo bin int err = 0;
42901f2b3daSLuo bin
43001f2b3daSLuo bin if (set_settings & HILINK_LINK_SET_AUTONEG) {
43101f2b3daSLuo bin err = hinic_set_autoneg(nic_dev->hwdev,
43201f2b3daSLuo bin (autoneg == AUTONEG_ENABLE));
43301f2b3daSLuo bin if (err)
43401f2b3daSLuo bin netif_err(nic_dev, drv, nic_dev->netdev, "%s autoneg failed\n",
43501f2b3daSLuo bin (autoneg == AUTONEG_ENABLE) ?
43601f2b3daSLuo bin "Enable" : "Disable");
43701f2b3daSLuo bin else
43801f2b3daSLuo bin netif_info(nic_dev, drv, nic_dev->netdev, "%s autoneg successfully\n",
43901f2b3daSLuo bin (autoneg == AUTONEG_ENABLE) ?
44001f2b3daSLuo bin "Enable" : "Disable");
44101f2b3daSLuo bin }
44201f2b3daSLuo bin
44301f2b3daSLuo bin if (!err && (set_settings & HILINK_LINK_SET_SPEED)) {
44401f2b3daSLuo bin speed_level = hinic_ethtool_to_hw_speed_level(speed);
44501f2b3daSLuo bin err = hinic_set_speed(nic_dev->hwdev, speed_level);
44601f2b3daSLuo bin if (err)
44701f2b3daSLuo bin netif_err(nic_dev, drv, nic_dev->netdev, "Set speed %d failed\n",
44801f2b3daSLuo bin speed);
44901f2b3daSLuo bin else
45001f2b3daSLuo bin netif_info(nic_dev, drv, nic_dev->netdev, "Set speed %d successfully\n",
45101f2b3daSLuo bin speed);
45201f2b3daSLuo bin }
45301f2b3daSLuo bin
45401f2b3daSLuo bin return err;
45501f2b3daSLuo bin }
45601f2b3daSLuo bin
hinic_set_settings_to_hw(struct hinic_dev * nic_dev,u32 set_settings,u8 autoneg,u32 speed)45701f2b3daSLuo bin static int hinic_set_settings_to_hw(struct hinic_dev *nic_dev,
45801f2b3daSLuo bin u32 set_settings, u8 autoneg, u32 speed)
45901f2b3daSLuo bin {
46001f2b3daSLuo bin struct hinic_link_ksettings_info settings = {0};
46101f2b3daSLuo bin char set_link_str[SET_LINK_STR_MAX_LEN] = {0};
46284c7f6c3SArnd Bergmann const char *autoneg_str;
46301f2b3daSLuo bin struct net_device *netdev = nic_dev->netdev;
46401f2b3daSLuo bin enum nic_speed_level speed_level = 0;
46501f2b3daSLuo bin int err;
46601f2b3daSLuo bin
46784c7f6c3SArnd Bergmann autoneg_str = (set_settings & HILINK_LINK_SET_AUTONEG) ?
46884c7f6c3SArnd Bergmann (autoneg ? "autong enable " : "autong disable ") : "";
46901f2b3daSLuo bin
47001f2b3daSLuo bin if (set_settings & HILINK_LINK_SET_SPEED) {
47101f2b3daSLuo bin speed_level = hinic_ethtool_to_hw_speed_level(speed);
47201f2b3daSLuo bin err = snprintf(set_link_str, SET_LINK_STR_MAX_LEN,
47384c7f6c3SArnd Bergmann "speed %d ", speed);
47484c7f6c3SArnd Bergmann if (err >= SET_LINK_STR_MAX_LEN) {
47501f2b3daSLuo bin netif_err(nic_dev, drv, netdev, "Failed to snprintf link speed, function return(%d) and dest_len(%d)\n",
47601f2b3daSLuo bin err, SET_LINK_STR_MAX_LEN);
47701f2b3daSLuo bin return -EFAULT;
47801f2b3daSLuo bin }
47901f2b3daSLuo bin }
48001f2b3daSLuo bin
48101f2b3daSLuo bin settings.func_id = HINIC_HWIF_FUNC_IDX(nic_dev->hwdev->hwif);
48201f2b3daSLuo bin settings.valid_bitmap = set_settings;
48301f2b3daSLuo bin settings.autoneg = autoneg;
48401f2b3daSLuo bin settings.speed = speed_level;
48501f2b3daSLuo bin
48601f2b3daSLuo bin err = hinic_set_link_settings(nic_dev->hwdev, &settings);
48701f2b3daSLuo bin if (err != HINIC_MGMT_CMD_UNSUPPORTED) {
48801f2b3daSLuo bin if (err)
48984c7f6c3SArnd Bergmann netif_err(nic_dev, drv, netdev, "Set %s%sfailed\n",
49084c7f6c3SArnd Bergmann autoneg_str, set_link_str);
49101f2b3daSLuo bin else
49284c7f6c3SArnd Bergmann netif_info(nic_dev, drv, netdev, "Set %s%ssuccessfully\n",
49384c7f6c3SArnd Bergmann autoneg_str, set_link_str);
49401f2b3daSLuo bin
49501f2b3daSLuo bin return err;
49601f2b3daSLuo bin }
49701f2b3daSLuo bin
49801f2b3daSLuo bin return set_link_settings_separate_cmd(nic_dev, set_settings, autoneg,
49901f2b3daSLuo bin speed);
50001f2b3daSLuo bin }
50101f2b3daSLuo bin
set_link_settings(struct net_device * netdev,u8 autoneg,u32 speed)50201f2b3daSLuo bin static int set_link_settings(struct net_device *netdev, u8 autoneg, u32 speed)
50301f2b3daSLuo bin {
50401f2b3daSLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
50501f2b3daSLuo bin u32 set_settings = 0;
50601f2b3daSLuo bin int err;
50701f2b3daSLuo bin
50801f2b3daSLuo bin err = get_link_settings_type(nic_dev, autoneg, speed, &set_settings);
50901f2b3daSLuo bin if (err)
51001f2b3daSLuo bin return err;
51101f2b3daSLuo bin
51201f2b3daSLuo bin if (set_settings)
51301f2b3daSLuo bin err = hinic_set_settings_to_hw(nic_dev, set_settings,
51401f2b3daSLuo bin autoneg, speed);
51501f2b3daSLuo bin else
51601f2b3daSLuo bin netif_info(nic_dev, drv, netdev, "Nothing changed, exit without setting anything\n");
51701f2b3daSLuo bin
51801f2b3daSLuo bin return err;
51901f2b3daSLuo bin }
52001f2b3daSLuo bin
hinic_set_link_ksettings(struct net_device * netdev,const struct ethtool_link_ksettings * link_settings)52101f2b3daSLuo bin static int hinic_set_link_ksettings(struct net_device *netdev, const struct
52201f2b3daSLuo bin ethtool_link_ksettings *link_settings)
52301f2b3daSLuo bin {
52401f2b3daSLuo bin /* only support to set autoneg and speed */
52501f2b3daSLuo bin return set_link_settings(netdev, link_settings->base.autoneg,
52601f2b3daSLuo bin link_settings->base.speed);
52701f2b3daSLuo bin }
52801f2b3daSLuo bin
hinic_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * info)529eb8ce9acSXue Chaojing static void hinic_get_drvinfo(struct net_device *netdev,
530eb8ce9acSXue Chaojing struct ethtool_drvinfo *info)
531eb8ce9acSXue Chaojing {
532eb8ce9acSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
53361a582beSXue Chaojing u8 mgmt_ver[HINIC_MGMT_VERSION_MAX_LEN] = {0};
534eb8ce9acSXue Chaojing struct hinic_hwdev *hwdev = nic_dev->hwdev;
535eb8ce9acSXue Chaojing struct hinic_hwif *hwif = hwdev->hwif;
53661a582beSXue Chaojing int err;
537eb8ce9acSXue Chaojing
53879d65cabSDaode Huang strscpy(info->driver, HINIC_DRV_NAME, sizeof(info->driver));
53979d65cabSDaode Huang strscpy(info->bus_info, pci_name(hwif->pdev), sizeof(info->bus_info));
54061a582beSXue Chaojing
54161a582beSXue Chaojing err = hinic_get_mgmt_version(nic_dev, mgmt_ver);
54261a582beSXue Chaojing if (err)
54361a582beSXue Chaojing return;
54461a582beSXue Chaojing
54561a582beSXue Chaojing snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver);
546eb8ce9acSXue Chaojing }
547eb8ce9acSXue Chaojing
hinic_get_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)548eb8ce9acSXue Chaojing static void hinic_get_ringparam(struct net_device *netdev,
549*74624944SHao Chen struct ethtool_ringparam *ring,
550*74624944SHao Chen struct kernel_ethtool_ringparam *kernel_ring,
551*74624944SHao Chen struct netlink_ext_ack *extack)
552eb8ce9acSXue Chaojing {
553bcab6782SLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
554bcab6782SLuo bin
555bcab6782SLuo bin ring->rx_max_pending = HINIC_MAX_QUEUE_DEPTH;
556bcab6782SLuo bin ring->tx_max_pending = HINIC_MAX_QUEUE_DEPTH;
557bcab6782SLuo bin ring->rx_pending = nic_dev->rq_depth;
558bcab6782SLuo bin ring->tx_pending = nic_dev->sq_depth;
559eb8ce9acSXue Chaojing }
560eb8ce9acSXue Chaojing
check_ringparam_valid(struct hinic_dev * nic_dev,struct ethtool_ringparam * ring)561bcab6782SLuo bin static int check_ringparam_valid(struct hinic_dev *nic_dev,
562bcab6782SLuo bin struct ethtool_ringparam *ring)
563bcab6782SLuo bin {
564bcab6782SLuo bin if (ring->rx_jumbo_pending || ring->rx_mini_pending) {
565bcab6782SLuo bin netif_err(nic_dev, drv, nic_dev->netdev,
566bcab6782SLuo bin "Unsupported rx_jumbo_pending/rx_mini_pending\n");
567bcab6782SLuo bin return -EINVAL;
568bcab6782SLuo bin }
569bcab6782SLuo bin
570bcab6782SLuo bin if (ring->tx_pending > HINIC_MAX_QUEUE_DEPTH ||
571bcab6782SLuo bin ring->tx_pending < HINIC_MIN_QUEUE_DEPTH ||
572bcab6782SLuo bin ring->rx_pending > HINIC_MAX_QUEUE_DEPTH ||
573bcab6782SLuo bin ring->rx_pending < HINIC_MIN_QUEUE_DEPTH) {
574bcab6782SLuo bin netif_err(nic_dev, drv, nic_dev->netdev,
575bcab6782SLuo bin "Queue depth out of range [%d-%d]\n",
576bcab6782SLuo bin HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH);
577bcab6782SLuo bin return -EINVAL;
578bcab6782SLuo bin }
579bcab6782SLuo bin
580bcab6782SLuo bin return 0;
581bcab6782SLuo bin }
582bcab6782SLuo bin
hinic_set_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)583bcab6782SLuo bin static int hinic_set_ringparam(struct net_device *netdev,
584*74624944SHao Chen struct ethtool_ringparam *ring,
585*74624944SHao Chen struct kernel_ethtool_ringparam *kernel_ring,
586*74624944SHao Chen struct netlink_ext_ack *extack)
587bcab6782SLuo bin {
588bcab6782SLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
589bcab6782SLuo bin u16 new_sq_depth, new_rq_depth;
590bcab6782SLuo bin int err;
591bcab6782SLuo bin
592bcab6782SLuo bin err = check_ringparam_valid(nic_dev, ring);
593bcab6782SLuo bin if (err)
594bcab6782SLuo bin return err;
595bcab6782SLuo bin
596bcab6782SLuo bin new_sq_depth = (u16)(1U << (u16)ilog2(ring->tx_pending));
597bcab6782SLuo bin new_rq_depth = (u16)(1U << (u16)ilog2(ring->rx_pending));
598bcab6782SLuo bin
599bcab6782SLuo bin if (new_sq_depth == nic_dev->sq_depth &&
600bcab6782SLuo bin new_rq_depth == nic_dev->rq_depth)
601bcab6782SLuo bin return 0;
602bcab6782SLuo bin
603bcab6782SLuo bin netif_info(nic_dev, drv, netdev,
604bcab6782SLuo bin "Change Tx/Rx ring depth from %d/%d to %d/%d\n",
605bcab6782SLuo bin nic_dev->sq_depth, nic_dev->rq_depth,
606bcab6782SLuo bin new_sq_depth, new_rq_depth);
607bcab6782SLuo bin
608bcab6782SLuo bin nic_dev->sq_depth = new_sq_depth;
609bcab6782SLuo bin nic_dev->rq_depth = new_rq_depth;
610bcab6782SLuo bin
611bcab6782SLuo bin if (netif_running(netdev)) {
612bcab6782SLuo bin netif_info(nic_dev, drv, netdev, "Restarting netdev\n");
613bcab6782SLuo bin err = hinic_close(netdev);
614bcab6782SLuo bin if (err) {
615bcab6782SLuo bin netif_err(nic_dev, drv, netdev,
616bcab6782SLuo bin "Failed to close netdev\n");
617bcab6782SLuo bin return -EFAULT;
618bcab6782SLuo bin }
619bcab6782SLuo bin
620bcab6782SLuo bin err = hinic_open(netdev);
621bcab6782SLuo bin if (err) {
622bcab6782SLuo bin netif_err(nic_dev, drv, netdev,
623bcab6782SLuo bin "Failed to open netdev\n");
624bcab6782SLuo bin return -EFAULT;
625bcab6782SLuo bin }
626bcab6782SLuo bin }
627bcab6782SLuo bin
628bcab6782SLuo bin return 0;
629bcab6782SLuo bin }
630ea256222SLuo bin
__hinic_get_coalesce(struct net_device * netdev,struct ethtool_coalesce * coal,u16 queue)631a0337c0dSLuo bin static int __hinic_get_coalesce(struct net_device *netdev,
632a0337c0dSLuo bin struct ethtool_coalesce *coal, u16 queue)
633a0337c0dSLuo bin {
634a0337c0dSLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
635a0337c0dSLuo bin struct hinic_intr_coal_info *rx_intr_coal_info;
636a0337c0dSLuo bin struct hinic_intr_coal_info *tx_intr_coal_info;
637a0337c0dSLuo bin
638a0337c0dSLuo bin if (queue == COALESCE_ALL_QUEUE) {
639a0337c0dSLuo bin /* get tx/rx irq0 as default parameters */
640a0337c0dSLuo bin rx_intr_coal_info = &nic_dev->rx_intr_coalesce[0];
641a0337c0dSLuo bin tx_intr_coal_info = &nic_dev->tx_intr_coalesce[0];
642a0337c0dSLuo bin } else {
643a0337c0dSLuo bin if (queue >= nic_dev->num_qps) {
644a0337c0dSLuo bin netif_err(nic_dev, drv, netdev,
645a0337c0dSLuo bin "Invalid queue_id: %d\n", queue);
646a0337c0dSLuo bin return -EINVAL;
647a0337c0dSLuo bin }
648a0337c0dSLuo bin rx_intr_coal_info = &nic_dev->rx_intr_coalesce[queue];
649a0337c0dSLuo bin tx_intr_coal_info = &nic_dev->tx_intr_coalesce[queue];
650a0337c0dSLuo bin }
651a0337c0dSLuo bin
652a0337c0dSLuo bin /* coalesce_timer is in unit of 9us */
653a0337c0dSLuo bin coal->rx_coalesce_usecs = rx_intr_coal_info->coalesce_timer_cfg *
654a0337c0dSLuo bin COALESCE_TIMER_CFG_UNIT;
655a0337c0dSLuo bin /* coalesced_frames is in unit of 8 */
656a0337c0dSLuo bin coal->rx_max_coalesced_frames = rx_intr_coal_info->pending_limt *
657a0337c0dSLuo bin COALESCE_PENDING_LIMIT_UNIT;
658a0337c0dSLuo bin coal->tx_coalesce_usecs = tx_intr_coal_info->coalesce_timer_cfg *
659a0337c0dSLuo bin COALESCE_TIMER_CFG_UNIT;
660a0337c0dSLuo bin coal->tx_max_coalesced_frames = tx_intr_coal_info->pending_limt *
661a0337c0dSLuo bin COALESCE_PENDING_LIMIT_UNIT;
662a0337c0dSLuo bin
663a0337c0dSLuo bin return 0;
664a0337c0dSLuo bin }
665a0337c0dSLuo bin
is_coalesce_exceed_limit(const struct ethtool_coalesce * coal)666a0337c0dSLuo bin static int is_coalesce_exceed_limit(const struct ethtool_coalesce *coal)
667a0337c0dSLuo bin {
668a0337c0dSLuo bin if (coal->rx_coalesce_usecs > COALESCE_MAX_TIMER_CFG ||
669a0337c0dSLuo bin coal->rx_max_coalesced_frames > COALESCE_MAX_PENDING_LIMIT ||
670a0337c0dSLuo bin coal->tx_coalesce_usecs > COALESCE_MAX_TIMER_CFG ||
671a0337c0dSLuo bin coal->tx_max_coalesced_frames > COALESCE_MAX_PENDING_LIMIT)
672a0337c0dSLuo bin return -ERANGE;
673a0337c0dSLuo bin
674a0337c0dSLuo bin return 0;
675a0337c0dSLuo bin }
676a0337c0dSLuo bin
set_queue_coalesce(struct hinic_dev * nic_dev,u16 q_id,struct hinic_intr_coal_info * coal,bool set_rx_coal)677a0337c0dSLuo bin static int set_queue_coalesce(struct hinic_dev *nic_dev, u16 q_id,
678a0337c0dSLuo bin struct hinic_intr_coal_info *coal,
679a0337c0dSLuo bin bool set_rx_coal)
680a0337c0dSLuo bin {
681a0337c0dSLuo bin struct hinic_intr_coal_info *intr_coal = NULL;
682a0337c0dSLuo bin struct hinic_msix_config interrupt_info = {0};
683a0337c0dSLuo bin struct net_device *netdev = nic_dev->netdev;
684a0337c0dSLuo bin u16 msix_idx;
685a0337c0dSLuo bin int err;
686a0337c0dSLuo bin
687a0337c0dSLuo bin intr_coal = set_rx_coal ? &nic_dev->rx_intr_coalesce[q_id] :
688a0337c0dSLuo bin &nic_dev->tx_intr_coalesce[q_id];
689a0337c0dSLuo bin
690a0337c0dSLuo bin intr_coal->coalesce_timer_cfg = coal->coalesce_timer_cfg;
691a0337c0dSLuo bin intr_coal->pending_limt = coal->pending_limt;
692a0337c0dSLuo bin
693a0337c0dSLuo bin /* netdev not running or qp not in using,
694a0337c0dSLuo bin * don't need to set coalesce to hw
695a0337c0dSLuo bin */
696a0337c0dSLuo bin if (!(nic_dev->flags & HINIC_INTF_UP) ||
697a0337c0dSLuo bin q_id >= nic_dev->num_qps)
698a0337c0dSLuo bin return 0;
699a0337c0dSLuo bin
700a0337c0dSLuo bin msix_idx = set_rx_coal ? nic_dev->rxqs[q_id].rq->msix_entry :
701a0337c0dSLuo bin nic_dev->txqs[q_id].sq->msix_entry;
702a0337c0dSLuo bin interrupt_info.msix_index = msix_idx;
703a0337c0dSLuo bin interrupt_info.coalesce_timer_cnt = intr_coal->coalesce_timer_cfg;
704a0337c0dSLuo bin interrupt_info.pending_cnt = intr_coal->pending_limt;
705a0337c0dSLuo bin interrupt_info.resend_timer_cnt = intr_coal->resend_timer_cfg;
706a0337c0dSLuo bin
707a0337c0dSLuo bin err = hinic_set_interrupt_cfg(nic_dev->hwdev, &interrupt_info);
708a0337c0dSLuo bin if (err)
709a0337c0dSLuo bin netif_warn(nic_dev, drv, netdev,
710a0337c0dSLuo bin "Failed to set %s queue%d coalesce",
711a0337c0dSLuo bin set_rx_coal ? "rx" : "tx", q_id);
712a0337c0dSLuo bin
713a0337c0dSLuo bin return err;
714a0337c0dSLuo bin }
715a0337c0dSLuo bin
__set_hw_coal_param(struct hinic_dev * nic_dev,struct hinic_intr_coal_info * intr_coal,u16 queue,bool set_rx_coal)716a0337c0dSLuo bin static int __set_hw_coal_param(struct hinic_dev *nic_dev,
717a0337c0dSLuo bin struct hinic_intr_coal_info *intr_coal,
718a0337c0dSLuo bin u16 queue, bool set_rx_coal)
719a0337c0dSLuo bin {
720a0337c0dSLuo bin int err;
721a0337c0dSLuo bin u16 i;
722a0337c0dSLuo bin
723a0337c0dSLuo bin if (queue == COALESCE_ALL_QUEUE) {
724a0337c0dSLuo bin for (i = 0; i < nic_dev->max_qps; i++) {
725a0337c0dSLuo bin err = set_queue_coalesce(nic_dev, i, intr_coal,
726a0337c0dSLuo bin set_rx_coal);
727a0337c0dSLuo bin if (err)
728a0337c0dSLuo bin return err;
729a0337c0dSLuo bin }
730a0337c0dSLuo bin } else {
731a0337c0dSLuo bin if (queue >= nic_dev->num_qps) {
732a0337c0dSLuo bin netif_err(nic_dev, drv, nic_dev->netdev,
733a0337c0dSLuo bin "Invalid queue_id: %d\n", queue);
734a0337c0dSLuo bin return -EINVAL;
735a0337c0dSLuo bin }
736a0337c0dSLuo bin err = set_queue_coalesce(nic_dev, queue, intr_coal,
737a0337c0dSLuo bin set_rx_coal);
738a0337c0dSLuo bin if (err)
739a0337c0dSLuo bin return err;
740a0337c0dSLuo bin }
741a0337c0dSLuo bin
742a0337c0dSLuo bin return 0;
743a0337c0dSLuo bin }
744a0337c0dSLuo bin
__hinic_set_coalesce(struct net_device * netdev,struct ethtool_coalesce * coal,u16 queue)745a0337c0dSLuo bin static int __hinic_set_coalesce(struct net_device *netdev,
746a0337c0dSLuo bin struct ethtool_coalesce *coal, u16 queue)
747a0337c0dSLuo bin {
748a0337c0dSLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
749a0337c0dSLuo bin struct hinic_intr_coal_info rx_intr_coal = {0};
750a0337c0dSLuo bin struct hinic_intr_coal_info tx_intr_coal = {0};
751a0337c0dSLuo bin bool set_rx_coal = false;
752a0337c0dSLuo bin bool set_tx_coal = false;
753a0337c0dSLuo bin int err;
754a0337c0dSLuo bin
755a0337c0dSLuo bin err = is_coalesce_exceed_limit(coal);
756a0337c0dSLuo bin if (err)
757a0337c0dSLuo bin return err;
758a0337c0dSLuo bin
759a0337c0dSLuo bin if (coal->rx_coalesce_usecs || coal->rx_max_coalesced_frames) {
760a0337c0dSLuo bin rx_intr_coal.coalesce_timer_cfg =
761a0337c0dSLuo bin (u8)(coal->rx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT);
762a0337c0dSLuo bin rx_intr_coal.pending_limt = (u8)(coal->rx_max_coalesced_frames /
763a0337c0dSLuo bin COALESCE_PENDING_LIMIT_UNIT);
764a0337c0dSLuo bin set_rx_coal = true;
765a0337c0dSLuo bin }
766a0337c0dSLuo bin
767a0337c0dSLuo bin if (coal->tx_coalesce_usecs || coal->tx_max_coalesced_frames) {
768a0337c0dSLuo bin tx_intr_coal.coalesce_timer_cfg =
769a0337c0dSLuo bin (u8)(coal->tx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT);
770a0337c0dSLuo bin tx_intr_coal.pending_limt = (u8)(coal->tx_max_coalesced_frames /
771a0337c0dSLuo bin COALESCE_PENDING_LIMIT_UNIT);
772a0337c0dSLuo bin set_tx_coal = true;
773a0337c0dSLuo bin }
774a0337c0dSLuo bin
775a0337c0dSLuo bin /* setting coalesce timer or pending limit to zero will disable
776a0337c0dSLuo bin * coalesce
777a0337c0dSLuo bin */
778a0337c0dSLuo bin if (set_rx_coal && (!rx_intr_coal.coalesce_timer_cfg ||
779a0337c0dSLuo bin !rx_intr_coal.pending_limt))
780a0337c0dSLuo bin netif_warn(nic_dev, drv, netdev, "RX coalesce will be disabled\n");
781a0337c0dSLuo bin if (set_tx_coal && (!tx_intr_coal.coalesce_timer_cfg ||
782a0337c0dSLuo bin !tx_intr_coal.pending_limt))
783a0337c0dSLuo bin netif_warn(nic_dev, drv, netdev, "TX coalesce will be disabled\n");
784a0337c0dSLuo bin
785a0337c0dSLuo bin if (set_rx_coal) {
786a0337c0dSLuo bin err = __set_hw_coal_param(nic_dev, &rx_intr_coal, queue, true);
787a0337c0dSLuo bin if (err)
788a0337c0dSLuo bin return err;
789a0337c0dSLuo bin }
790a0337c0dSLuo bin if (set_tx_coal) {
791a0337c0dSLuo bin err = __set_hw_coal_param(nic_dev, &tx_intr_coal, queue, false);
792a0337c0dSLuo bin if (err)
793a0337c0dSLuo bin return err;
794a0337c0dSLuo bin }
795a0337c0dSLuo bin return 0;
796a0337c0dSLuo bin }
797a0337c0dSLuo bin
hinic_get_coalesce(struct net_device * netdev,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)798a0337c0dSLuo bin static int hinic_get_coalesce(struct net_device *netdev,
799f3ccfda1SYufeng Mo struct ethtool_coalesce *coal,
800f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
801f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
802a0337c0dSLuo bin {
803a0337c0dSLuo bin return __hinic_get_coalesce(netdev, coal, COALESCE_ALL_QUEUE);
804a0337c0dSLuo bin }
805a0337c0dSLuo bin
hinic_set_coalesce(struct net_device * netdev,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)806a0337c0dSLuo bin static int hinic_set_coalesce(struct net_device *netdev,
807f3ccfda1SYufeng Mo struct ethtool_coalesce *coal,
808f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
809f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
810a0337c0dSLuo bin {
811a0337c0dSLuo bin return __hinic_set_coalesce(netdev, coal, COALESCE_ALL_QUEUE);
812a0337c0dSLuo bin }
813a0337c0dSLuo bin
hinic_get_per_queue_coalesce(struct net_device * netdev,u32 queue,struct ethtool_coalesce * coal)814a0337c0dSLuo bin static int hinic_get_per_queue_coalesce(struct net_device *netdev, u32 queue,
815a0337c0dSLuo bin struct ethtool_coalesce *coal)
816a0337c0dSLuo bin {
817a0337c0dSLuo bin return __hinic_get_coalesce(netdev, coal, queue);
818a0337c0dSLuo bin }
819a0337c0dSLuo bin
hinic_set_per_queue_coalesce(struct net_device * netdev,u32 queue,struct ethtool_coalesce * coal)820a0337c0dSLuo bin static int hinic_set_per_queue_coalesce(struct net_device *netdev, u32 queue,
821a0337c0dSLuo bin struct ethtool_coalesce *coal)
822a0337c0dSLuo bin {
823a0337c0dSLuo bin return __hinic_set_coalesce(netdev, coal, queue);
824a0337c0dSLuo bin }
825a0337c0dSLuo bin
hinic_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)826ea256222SLuo bin static void hinic_get_pauseparam(struct net_device *netdev,
827ea256222SLuo bin struct ethtool_pauseparam *pause)
828ea256222SLuo bin {
829ea256222SLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
830ea256222SLuo bin struct hinic_pause_config pause_info = {0};
831ea256222SLuo bin struct hinic_nic_cfg *nic_cfg;
832ea256222SLuo bin int err;
833ea256222SLuo bin
834ea256222SLuo bin nic_cfg = &nic_dev->hwdev->func_to_io.nic_cfg;
835ea256222SLuo bin
836ea256222SLuo bin err = hinic_get_hw_pause_info(nic_dev->hwdev, &pause_info);
837ea256222SLuo bin if (!err) {
838ea256222SLuo bin pause->autoneg = pause_info.auto_neg;
839ea256222SLuo bin if (nic_cfg->pause_set || !pause_info.auto_neg) {
840ea256222SLuo bin pause->rx_pause = nic_cfg->rx_pause;
841ea256222SLuo bin pause->tx_pause = nic_cfg->tx_pause;
842ea256222SLuo bin } else {
843ea256222SLuo bin pause->rx_pause = pause_info.rx_pause;
844ea256222SLuo bin pause->tx_pause = pause_info.tx_pause;
845ea256222SLuo bin }
846ea256222SLuo bin }
847ea256222SLuo bin }
848ea256222SLuo bin
hinic_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)849ea256222SLuo bin static int hinic_set_pauseparam(struct net_device *netdev,
850ea256222SLuo bin struct ethtool_pauseparam *pause)
851ea256222SLuo bin {
852ea256222SLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
853ea256222SLuo bin struct hinic_pause_config pause_info = {0};
854ea256222SLuo bin struct hinic_port_cap port_cap = {0};
855ea256222SLuo bin int err;
856ea256222SLuo bin
857ea256222SLuo bin err = hinic_port_get_cap(nic_dev, &port_cap);
858ea256222SLuo bin if (err)
859ea256222SLuo bin return -EIO;
860ea256222SLuo bin
861ea256222SLuo bin if (pause->autoneg != port_cap.autoneg_state)
862ea256222SLuo bin return -EOPNOTSUPP;
863ea256222SLuo bin
864ea256222SLuo bin pause_info.auto_neg = pause->autoneg;
865ea256222SLuo bin pause_info.rx_pause = pause->rx_pause;
866ea256222SLuo bin pause_info.tx_pause = pause->tx_pause;
867ea256222SLuo bin
868ea256222SLuo bin mutex_lock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);
869ea256222SLuo bin err = hinic_set_hw_pause_info(nic_dev->hwdev, &pause_info);
870ea256222SLuo bin if (err) {
871ea256222SLuo bin mutex_unlock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);
872ea256222SLuo bin return err;
873ea256222SLuo bin }
874ea256222SLuo bin nic_dev->hwdev->func_to_io.nic_cfg.pause_set = true;
875ea256222SLuo bin nic_dev->hwdev->func_to_io.nic_cfg.auto_neg = pause->autoneg;
876ea256222SLuo bin nic_dev->hwdev->func_to_io.nic_cfg.rx_pause = pause->rx_pause;
877ea256222SLuo bin nic_dev->hwdev->func_to_io.nic_cfg.tx_pause = pause->tx_pause;
878ea256222SLuo bin mutex_unlock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);
879ea256222SLuo bin
880ea256222SLuo bin return 0;
881ea256222SLuo bin }
882ea256222SLuo bin
hinic_get_channels(struct net_device * netdev,struct ethtool_channels * channels)883eb8ce9acSXue Chaojing static void hinic_get_channels(struct net_device *netdev,
884eb8ce9acSXue Chaojing struct ethtool_channels *channels)
885eb8ce9acSXue Chaojing {
886eb8ce9acSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
887eb8ce9acSXue Chaojing struct hinic_hwdev *hwdev = nic_dev->hwdev;
888eb8ce9acSXue Chaojing
8892eed5a8bSLuo bin channels->max_combined = nic_dev->max_qps;
8902eed5a8bSLuo bin channels->combined_count = hinic_hwdev_num_qps(hwdev);
8912eed5a8bSLuo bin }
8922eed5a8bSLuo bin
hinic_set_channels(struct net_device * netdev,struct ethtool_channels * channels)8932eed5a8bSLuo bin static int hinic_set_channels(struct net_device *netdev,
8942eed5a8bSLuo bin struct ethtool_channels *channels)
8952eed5a8bSLuo bin {
8962eed5a8bSLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
8972eed5a8bSLuo bin unsigned int count = channels->combined_count;
8982eed5a8bSLuo bin int err;
8992eed5a8bSLuo bin
9002eed5a8bSLuo bin netif_info(nic_dev, drv, netdev, "Set max combined queue number from %d to %d\n",
9012eed5a8bSLuo bin hinic_hwdev_num_qps(nic_dev->hwdev), count);
9022eed5a8bSLuo bin
9032eed5a8bSLuo bin if (netif_running(netdev)) {
9042eed5a8bSLuo bin netif_info(nic_dev, drv, netdev, "Restarting netdev\n");
9052eed5a8bSLuo bin hinic_close(netdev);
9062eed5a8bSLuo bin
9072eed5a8bSLuo bin nic_dev->hwdev->nic_cap.num_qps = count;
9082eed5a8bSLuo bin
9092eed5a8bSLuo bin err = hinic_open(netdev);
9102eed5a8bSLuo bin if (err) {
9112eed5a8bSLuo bin netif_err(nic_dev, drv, netdev,
9122eed5a8bSLuo bin "Failed to open netdev\n");
9132eed5a8bSLuo bin return -EFAULT;
9142eed5a8bSLuo bin }
9152eed5a8bSLuo bin } else {
9162eed5a8bSLuo bin nic_dev->hwdev->nic_cap.num_qps = count;
9172eed5a8bSLuo bin }
9182eed5a8bSLuo bin
9192eed5a8bSLuo bin return 0;
920eb8ce9acSXue Chaojing }
921eb8ce9acSXue Chaojing
hinic_get_rss_hash_opts(struct hinic_dev * nic_dev,struct ethtool_rxnfc * cmd)9224fdc51bbSXue Chaojing static int hinic_get_rss_hash_opts(struct hinic_dev *nic_dev,
9234fdc51bbSXue Chaojing struct ethtool_rxnfc *cmd)
9244fdc51bbSXue Chaojing {
9254fdc51bbSXue Chaojing struct hinic_rss_type rss_type = { 0 };
9264fdc51bbSXue Chaojing int err;
9274fdc51bbSXue Chaojing
9284fdc51bbSXue Chaojing cmd->data = 0;
9294fdc51bbSXue Chaojing
9304fdc51bbSXue Chaojing if (!(nic_dev->flags & HINIC_RSS_ENABLE))
9314fdc51bbSXue Chaojing return 0;
9324fdc51bbSXue Chaojing
9334fdc51bbSXue Chaojing err = hinic_get_rss_type(nic_dev, nic_dev->rss_tmpl_idx,
9344fdc51bbSXue Chaojing &rss_type);
9354fdc51bbSXue Chaojing if (err)
9364fdc51bbSXue Chaojing return err;
9374fdc51bbSXue Chaojing
9384fdc51bbSXue Chaojing cmd->data = RXH_IP_SRC | RXH_IP_DST;
9394fdc51bbSXue Chaojing switch (cmd->flow_type) {
9404fdc51bbSXue Chaojing case TCP_V4_FLOW:
9414fdc51bbSXue Chaojing if (rss_type.tcp_ipv4)
9424fdc51bbSXue Chaojing cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
9434fdc51bbSXue Chaojing break;
9444fdc51bbSXue Chaojing case TCP_V6_FLOW:
9454fdc51bbSXue Chaojing if (rss_type.tcp_ipv6)
9464fdc51bbSXue Chaojing cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
9474fdc51bbSXue Chaojing break;
9484fdc51bbSXue Chaojing case UDP_V4_FLOW:
9494fdc51bbSXue Chaojing if (rss_type.udp_ipv4)
9504fdc51bbSXue Chaojing cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
9514fdc51bbSXue Chaojing break;
9524fdc51bbSXue Chaojing case UDP_V6_FLOW:
9534fdc51bbSXue Chaojing if (rss_type.udp_ipv6)
9544fdc51bbSXue Chaojing cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
9554fdc51bbSXue Chaojing break;
9564fdc51bbSXue Chaojing case IPV4_FLOW:
9574fdc51bbSXue Chaojing case IPV6_FLOW:
9584fdc51bbSXue Chaojing break;
9594fdc51bbSXue Chaojing default:
9604fdc51bbSXue Chaojing cmd->data = 0;
9614fdc51bbSXue Chaojing return -EINVAL;
9624fdc51bbSXue Chaojing }
9634fdc51bbSXue Chaojing
9644fdc51bbSXue Chaojing return 0;
9654fdc51bbSXue Chaojing }
9664fdc51bbSXue Chaojing
set_l4_rss_hash_ops(struct ethtool_rxnfc * cmd,struct hinic_rss_type * rss_type)9674fdc51bbSXue Chaojing static int set_l4_rss_hash_ops(struct ethtool_rxnfc *cmd,
9684fdc51bbSXue Chaojing struct hinic_rss_type *rss_type)
9694fdc51bbSXue Chaojing {
9704fdc51bbSXue Chaojing u8 rss_l4_en = 0;
9714fdc51bbSXue Chaojing
9724fdc51bbSXue Chaojing switch (cmd->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
9734fdc51bbSXue Chaojing case 0:
9744fdc51bbSXue Chaojing rss_l4_en = 0;
9754fdc51bbSXue Chaojing break;
9764fdc51bbSXue Chaojing case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
9774fdc51bbSXue Chaojing rss_l4_en = 1;
9784fdc51bbSXue Chaojing break;
9794fdc51bbSXue Chaojing default:
9804fdc51bbSXue Chaojing return -EINVAL;
9814fdc51bbSXue Chaojing }
9824fdc51bbSXue Chaojing
9834fdc51bbSXue Chaojing switch (cmd->flow_type) {
9844fdc51bbSXue Chaojing case TCP_V4_FLOW:
9854fdc51bbSXue Chaojing rss_type->tcp_ipv4 = rss_l4_en;
9864fdc51bbSXue Chaojing break;
9874fdc51bbSXue Chaojing case TCP_V6_FLOW:
9884fdc51bbSXue Chaojing rss_type->tcp_ipv6 = rss_l4_en;
9894fdc51bbSXue Chaojing break;
9904fdc51bbSXue Chaojing case UDP_V4_FLOW:
9914fdc51bbSXue Chaojing rss_type->udp_ipv4 = rss_l4_en;
9924fdc51bbSXue Chaojing break;
9934fdc51bbSXue Chaojing case UDP_V6_FLOW:
9944fdc51bbSXue Chaojing rss_type->udp_ipv6 = rss_l4_en;
9954fdc51bbSXue Chaojing break;
9964fdc51bbSXue Chaojing default:
9974fdc51bbSXue Chaojing return -EINVAL;
9984fdc51bbSXue Chaojing }
9994fdc51bbSXue Chaojing
10004fdc51bbSXue Chaojing return 0;
10014fdc51bbSXue Chaojing }
10024fdc51bbSXue Chaojing
hinic_set_rss_hash_opts(struct hinic_dev * nic_dev,struct ethtool_rxnfc * cmd)10034fdc51bbSXue Chaojing static int hinic_set_rss_hash_opts(struct hinic_dev *nic_dev,
10044fdc51bbSXue Chaojing struct ethtool_rxnfc *cmd)
10054fdc51bbSXue Chaojing {
10064fdc51bbSXue Chaojing struct hinic_rss_type *rss_type = &nic_dev->rss_type;
10074fdc51bbSXue Chaojing int err;
10084fdc51bbSXue Chaojing
10094fdc51bbSXue Chaojing if (!(nic_dev->flags & HINIC_RSS_ENABLE)) {
10104fdc51bbSXue Chaojing cmd->data = 0;
10114fdc51bbSXue Chaojing return -EOPNOTSUPP;
10124fdc51bbSXue Chaojing }
10134fdc51bbSXue Chaojing
10144fdc51bbSXue Chaojing /* RSS does not support anything other than hashing
10154fdc51bbSXue Chaojing * to queues on src and dst IPs and ports
10164fdc51bbSXue Chaojing */
10174fdc51bbSXue Chaojing if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 |
10184fdc51bbSXue Chaojing RXH_L4_B_2_3))
10194fdc51bbSXue Chaojing return -EINVAL;
10204fdc51bbSXue Chaojing
10214fdc51bbSXue Chaojing /* We need at least the IP SRC and DEST fields for hashing */
10224fdc51bbSXue Chaojing if (!(cmd->data & RXH_IP_SRC) || !(cmd->data & RXH_IP_DST))
10234fdc51bbSXue Chaojing return -EINVAL;
10244fdc51bbSXue Chaojing
10254fdc51bbSXue Chaojing err = hinic_get_rss_type(nic_dev,
10264fdc51bbSXue Chaojing nic_dev->rss_tmpl_idx, rss_type);
10274fdc51bbSXue Chaojing if (err)
10284fdc51bbSXue Chaojing return -EFAULT;
10294fdc51bbSXue Chaojing
10304fdc51bbSXue Chaojing switch (cmd->flow_type) {
10314fdc51bbSXue Chaojing case TCP_V4_FLOW:
10324fdc51bbSXue Chaojing case TCP_V6_FLOW:
10334fdc51bbSXue Chaojing case UDP_V4_FLOW:
10344fdc51bbSXue Chaojing case UDP_V6_FLOW:
10354fdc51bbSXue Chaojing err = set_l4_rss_hash_ops(cmd, rss_type);
10364fdc51bbSXue Chaojing if (err)
10374fdc51bbSXue Chaojing return err;
10384fdc51bbSXue Chaojing break;
10394fdc51bbSXue Chaojing case IPV4_FLOW:
10404fdc51bbSXue Chaojing rss_type->ipv4 = 1;
10414fdc51bbSXue Chaojing break;
10424fdc51bbSXue Chaojing case IPV6_FLOW:
10434fdc51bbSXue Chaojing rss_type->ipv6 = 1;
10444fdc51bbSXue Chaojing break;
10454fdc51bbSXue Chaojing default:
10464fdc51bbSXue Chaojing return -EINVAL;
10474fdc51bbSXue Chaojing }
10484fdc51bbSXue Chaojing
10494fdc51bbSXue Chaojing err = hinic_set_rss_type(nic_dev, nic_dev->rss_tmpl_idx,
10504fdc51bbSXue Chaojing *rss_type);
10514fdc51bbSXue Chaojing if (err)
10524fdc51bbSXue Chaojing return -EFAULT;
10534fdc51bbSXue Chaojing
10544fdc51bbSXue Chaojing return 0;
10554fdc51bbSXue Chaojing }
10564fdc51bbSXue Chaojing
__set_rss_rxfh(struct net_device * netdev,const u32 * indir,const u8 * key)10574fdc51bbSXue Chaojing static int __set_rss_rxfh(struct net_device *netdev,
10584fdc51bbSXue Chaojing const u32 *indir, const u8 *key)
10594fdc51bbSXue Chaojing {
10604fdc51bbSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
10614fdc51bbSXue Chaojing int err;
10624fdc51bbSXue Chaojing
10634fdc51bbSXue Chaojing if (indir) {
10644fdc51bbSXue Chaojing if (!nic_dev->rss_indir_user) {
10654fdc51bbSXue Chaojing nic_dev->rss_indir_user =
10664fdc51bbSXue Chaojing kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE,
10674fdc51bbSXue Chaojing GFP_KERNEL);
10684fdc51bbSXue Chaojing if (!nic_dev->rss_indir_user)
10694fdc51bbSXue Chaojing return -ENOMEM;
10704fdc51bbSXue Chaojing }
10714fdc51bbSXue Chaojing
10724fdc51bbSXue Chaojing memcpy(nic_dev->rss_indir_user, indir,
10734fdc51bbSXue Chaojing sizeof(u32) * HINIC_RSS_INDIR_SIZE);
10744fdc51bbSXue Chaojing
10754fdc51bbSXue Chaojing err = hinic_rss_set_indir_tbl(nic_dev,
10764fdc51bbSXue Chaojing nic_dev->rss_tmpl_idx, indir);
10774fdc51bbSXue Chaojing if (err)
10784fdc51bbSXue Chaojing return -EFAULT;
10794fdc51bbSXue Chaojing }
10804fdc51bbSXue Chaojing
10814fdc51bbSXue Chaojing if (key) {
10824fdc51bbSXue Chaojing if (!nic_dev->rss_hkey_user) {
10834fdc51bbSXue Chaojing nic_dev->rss_hkey_user =
10844fdc51bbSXue Chaojing kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL);
10854fdc51bbSXue Chaojing
10864fdc51bbSXue Chaojing if (!nic_dev->rss_hkey_user)
10874fdc51bbSXue Chaojing return -ENOMEM;
10884fdc51bbSXue Chaojing }
10894fdc51bbSXue Chaojing
10904fdc51bbSXue Chaojing memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE);
10914fdc51bbSXue Chaojing
10924fdc51bbSXue Chaojing err = hinic_rss_set_template_tbl(nic_dev,
10934fdc51bbSXue Chaojing nic_dev->rss_tmpl_idx, key);
10944fdc51bbSXue Chaojing if (err)
10954fdc51bbSXue Chaojing return -EFAULT;
10964fdc51bbSXue Chaojing }
10974fdc51bbSXue Chaojing
10984fdc51bbSXue Chaojing return 0;
10994fdc51bbSXue Chaojing }
11004fdc51bbSXue Chaojing
hinic_get_rxnfc(struct net_device * netdev,struct ethtool_rxnfc * cmd,u32 * rule_locs)11014fdc51bbSXue Chaojing static int hinic_get_rxnfc(struct net_device *netdev,
11024fdc51bbSXue Chaojing struct ethtool_rxnfc *cmd, u32 *rule_locs)
11034fdc51bbSXue Chaojing {
11044fdc51bbSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
11054fdc51bbSXue Chaojing int err = 0;
11064fdc51bbSXue Chaojing
11074fdc51bbSXue Chaojing switch (cmd->cmd) {
11084fdc51bbSXue Chaojing case ETHTOOL_GRXRINGS:
11094fdc51bbSXue Chaojing cmd->data = nic_dev->num_qps;
11104fdc51bbSXue Chaojing break;
11114fdc51bbSXue Chaojing case ETHTOOL_GRXFH:
11124fdc51bbSXue Chaojing err = hinic_get_rss_hash_opts(nic_dev, cmd);
11134fdc51bbSXue Chaojing break;
11144fdc51bbSXue Chaojing default:
11154fdc51bbSXue Chaojing err = -EOPNOTSUPP;
11164fdc51bbSXue Chaojing break;
11174fdc51bbSXue Chaojing }
11184fdc51bbSXue Chaojing
11194fdc51bbSXue Chaojing return err;
11204fdc51bbSXue Chaojing }
11214fdc51bbSXue Chaojing
hinic_set_rxnfc(struct net_device * netdev,struct ethtool_rxnfc * cmd)11224fdc51bbSXue Chaojing static int hinic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
11234fdc51bbSXue Chaojing {
11244fdc51bbSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
11254fdc51bbSXue Chaojing int err = 0;
11264fdc51bbSXue Chaojing
11274fdc51bbSXue Chaojing switch (cmd->cmd) {
11284fdc51bbSXue Chaojing case ETHTOOL_SRXFH:
11294fdc51bbSXue Chaojing err = hinic_set_rss_hash_opts(nic_dev, cmd);
11304fdc51bbSXue Chaojing break;
11314fdc51bbSXue Chaojing default:
11324fdc51bbSXue Chaojing err = -EOPNOTSUPP;
11334fdc51bbSXue Chaojing break;
11344fdc51bbSXue Chaojing }
11354fdc51bbSXue Chaojing
11364fdc51bbSXue Chaojing return err;
11374fdc51bbSXue Chaojing }
11384fdc51bbSXue Chaojing
hinic_get_rxfh(struct net_device * netdev,u32 * indir,u8 * key,u8 * hfunc)11394fdc51bbSXue Chaojing static int hinic_get_rxfh(struct net_device *netdev,
11404fdc51bbSXue Chaojing u32 *indir, u8 *key, u8 *hfunc)
11414fdc51bbSXue Chaojing {
11424fdc51bbSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
11434fdc51bbSXue Chaojing u8 hash_engine_type = 0;
11444fdc51bbSXue Chaojing int err = 0;
11454fdc51bbSXue Chaojing
11464fdc51bbSXue Chaojing if (!(nic_dev->flags & HINIC_RSS_ENABLE))
11474fdc51bbSXue Chaojing return -EOPNOTSUPP;
11484fdc51bbSXue Chaojing
11494fdc51bbSXue Chaojing if (hfunc) {
11504fdc51bbSXue Chaojing err = hinic_rss_get_hash_engine(nic_dev,
11514fdc51bbSXue Chaojing nic_dev->rss_tmpl_idx,
11524fdc51bbSXue Chaojing &hash_engine_type);
11534fdc51bbSXue Chaojing if (err)
11544fdc51bbSXue Chaojing return -EFAULT;
11554fdc51bbSXue Chaojing
11564fdc51bbSXue Chaojing *hfunc = hash_engine_type ? ETH_RSS_HASH_TOP : ETH_RSS_HASH_XOR;
11574fdc51bbSXue Chaojing }
11584fdc51bbSXue Chaojing
11594fdc51bbSXue Chaojing if (indir) {
11604fdc51bbSXue Chaojing err = hinic_rss_get_indir_tbl(nic_dev,
11614fdc51bbSXue Chaojing nic_dev->rss_tmpl_idx, indir);
11624fdc51bbSXue Chaojing if (err)
11634fdc51bbSXue Chaojing return -EFAULT;
11644fdc51bbSXue Chaojing }
11654fdc51bbSXue Chaojing
11664fdc51bbSXue Chaojing if (key)
11674fdc51bbSXue Chaojing err = hinic_rss_get_template_tbl(nic_dev,
11684fdc51bbSXue Chaojing nic_dev->rss_tmpl_idx, key);
11694fdc51bbSXue Chaojing
11704fdc51bbSXue Chaojing return err;
11714fdc51bbSXue Chaojing }
11724fdc51bbSXue Chaojing
hinic_set_rxfh(struct net_device * netdev,const u32 * indir,const u8 * key,const u8 hfunc)11734fdc51bbSXue Chaojing static int hinic_set_rxfh(struct net_device *netdev, const u32 *indir,
11744fdc51bbSXue Chaojing const u8 *key, const u8 hfunc)
11754fdc51bbSXue Chaojing {
11764fdc51bbSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
11774fdc51bbSXue Chaojing int err = 0;
11784fdc51bbSXue Chaojing
11794fdc51bbSXue Chaojing if (!(nic_dev->flags & HINIC_RSS_ENABLE))
11804fdc51bbSXue Chaojing return -EOPNOTSUPP;
11814fdc51bbSXue Chaojing
11824fdc51bbSXue Chaojing if (hfunc != ETH_RSS_HASH_NO_CHANGE) {
11834fdc51bbSXue Chaojing if (hfunc != ETH_RSS_HASH_TOP && hfunc != ETH_RSS_HASH_XOR)
11844fdc51bbSXue Chaojing return -EOPNOTSUPP;
11854fdc51bbSXue Chaojing
11864fdc51bbSXue Chaojing nic_dev->rss_hash_engine = (hfunc == ETH_RSS_HASH_XOR) ?
11874fdc51bbSXue Chaojing HINIC_RSS_HASH_ENGINE_TYPE_XOR :
11884fdc51bbSXue Chaojing HINIC_RSS_HASH_ENGINE_TYPE_TOEP;
11894fdc51bbSXue Chaojing err = hinic_rss_set_hash_engine
11904fdc51bbSXue Chaojing (nic_dev, nic_dev->rss_tmpl_idx,
11914fdc51bbSXue Chaojing nic_dev->rss_hash_engine);
11924fdc51bbSXue Chaojing if (err)
11934fdc51bbSXue Chaojing return -EFAULT;
11944fdc51bbSXue Chaojing }
11954fdc51bbSXue Chaojing
11964fdc51bbSXue Chaojing err = __set_rss_rxfh(netdev, indir, key);
11974fdc51bbSXue Chaojing
11984fdc51bbSXue Chaojing return err;
11994fdc51bbSXue Chaojing }
12004fdc51bbSXue Chaojing
hinic_get_rxfh_key_size(struct net_device * netdev)12014fdc51bbSXue Chaojing static u32 hinic_get_rxfh_key_size(struct net_device *netdev)
12024fdc51bbSXue Chaojing {
12034fdc51bbSXue Chaojing return HINIC_RSS_KEY_SIZE;
12044fdc51bbSXue Chaojing }
12054fdc51bbSXue Chaojing
hinic_get_rxfh_indir_size(struct net_device * netdev)12064fdc51bbSXue Chaojing static u32 hinic_get_rxfh_indir_size(struct net_device *netdev)
12074fdc51bbSXue Chaojing {
12084fdc51bbSXue Chaojing return HINIC_RSS_INDIR_SIZE;
12094fdc51bbSXue Chaojing }
12104fdc51bbSXue Chaojing
1211e54fbbdfSXue Chaojing #define HINIC_FUNC_STAT(_stat_item) { \
1212e54fbbdfSXue Chaojing .name = #_stat_item, \
1213c593642cSPankaj Bharadiya .size = sizeof_field(struct hinic_vport_stats, _stat_item), \
1214e54fbbdfSXue Chaojing .offset = offsetof(struct hinic_vport_stats, _stat_item) \
1215e54fbbdfSXue Chaojing }
1216e54fbbdfSXue Chaojing
1217e54fbbdfSXue Chaojing static struct hinic_stats hinic_function_stats[] = {
1218e54fbbdfSXue Chaojing HINIC_FUNC_STAT(tx_unicast_pkts_vport),
1219e54fbbdfSXue Chaojing HINIC_FUNC_STAT(tx_unicast_bytes_vport),
1220e54fbbdfSXue Chaojing HINIC_FUNC_STAT(tx_multicast_pkts_vport),
1221e54fbbdfSXue Chaojing HINIC_FUNC_STAT(tx_multicast_bytes_vport),
1222e54fbbdfSXue Chaojing HINIC_FUNC_STAT(tx_broadcast_pkts_vport),
1223e54fbbdfSXue Chaojing HINIC_FUNC_STAT(tx_broadcast_bytes_vport),
1224e54fbbdfSXue Chaojing
1225e54fbbdfSXue Chaojing HINIC_FUNC_STAT(rx_unicast_pkts_vport),
1226e54fbbdfSXue Chaojing HINIC_FUNC_STAT(rx_unicast_bytes_vport),
1227e54fbbdfSXue Chaojing HINIC_FUNC_STAT(rx_multicast_pkts_vport),
1228e54fbbdfSXue Chaojing HINIC_FUNC_STAT(rx_multicast_bytes_vport),
1229e54fbbdfSXue Chaojing HINIC_FUNC_STAT(rx_broadcast_pkts_vport),
1230e54fbbdfSXue Chaojing HINIC_FUNC_STAT(rx_broadcast_bytes_vport),
1231e54fbbdfSXue Chaojing
1232e54fbbdfSXue Chaojing HINIC_FUNC_STAT(tx_discard_vport),
1233e54fbbdfSXue Chaojing HINIC_FUNC_STAT(rx_discard_vport),
1234e54fbbdfSXue Chaojing HINIC_FUNC_STAT(tx_err_vport),
1235e54fbbdfSXue Chaojing HINIC_FUNC_STAT(rx_err_vport),
1236e54fbbdfSXue Chaojing };
1237e54fbbdfSXue Chaojing
12384aa218a4SLuo bin static char hinic_test_strings[][ETH_GSTRING_LEN] = {
12394aa218a4SLuo bin "Internal lb test (on/offline)",
12404aa218a4SLuo bin "External lb test (external_lb)",
12414aa218a4SLuo bin };
12424aa218a4SLuo bin
1243e54fbbdfSXue Chaojing #define HINIC_PORT_STAT(_stat_item) { \
1244e54fbbdfSXue Chaojing .name = #_stat_item, \
1245c593642cSPankaj Bharadiya .size = sizeof_field(struct hinic_phy_port_stats, _stat_item), \
1246e54fbbdfSXue Chaojing .offset = offsetof(struct hinic_phy_port_stats, _stat_item) \
1247e54fbbdfSXue Chaojing }
1248e54fbbdfSXue Chaojing
1249e54fbbdfSXue Chaojing static struct hinic_stats hinic_port_stats[] = {
1250e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_total_pkt_num),
1251e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_total_oct_num),
1252e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_bad_pkt_num),
1253e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_bad_oct_num),
1254e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_good_pkt_num),
1255e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_good_oct_num),
1256e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_uni_pkt_num),
1257e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_multi_pkt_num),
1258e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_broad_pkt_num),
1259e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_total_pkt_num),
1260e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_total_oct_num),
1261e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_bad_pkt_num),
1262e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_bad_oct_num),
1263e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_good_pkt_num),
1264e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_good_oct_num),
1265e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_uni_pkt_num),
1266e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_multi_pkt_num),
1267e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_broad_pkt_num),
1268e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_fragment_pkt_num),
1269e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_undersize_pkt_num),
1270e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_undermin_pkt_num),
1271e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_64_oct_pkt_num),
1272e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_65_127_oct_pkt_num),
1273e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_128_255_oct_pkt_num),
1274e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_256_511_oct_pkt_num),
1275e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num),
1276e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num),
1277e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num),
1278e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num),
1279e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num),
1280e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num),
1281e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num),
1282e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num),
1283e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_1519_max_good_pkt_num),
1284e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num),
1285e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_oversize_pkt_num),
1286e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_jabber_pkt_num),
1287e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_pause_num),
1288e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_pfc_pkt_num),
1289e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num),
1290e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num),
1291e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num),
1292e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num),
1293e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num),
1294e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num),
1295e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num),
1296e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num),
1297e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_control_pkt_num),
1298e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_sym_err_pkt_num),
1299e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_fcs_err_pkt_num),
1300e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_send_app_good_pkt_num),
1301e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_rx_send_app_bad_pkt_num),
1302e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_fragment_pkt_num),
1303e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_undersize_pkt_num),
1304e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_undermin_pkt_num),
1305e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_64_oct_pkt_num),
1306e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_65_127_oct_pkt_num),
1307e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_128_255_oct_pkt_num),
1308e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_256_511_oct_pkt_num),
1309e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num),
1310e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num),
1311e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num),
1312e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num),
1313e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num),
1314e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num),
1315e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num),
1316e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num),
1317e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_1519_max_good_pkt_num),
1318e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num),
1319e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_oversize_pkt_num),
1320e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_jabber_pkt_num),
1321e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_pause_num),
1322e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_pfc_pkt_num),
1323e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num),
1324e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num),
1325e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num),
1326e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num),
1327e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num),
1328e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num),
1329e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num),
1330e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num),
1331e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_control_pkt_num),
1332e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_err_all_pkt_num),
1333e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_from_app_good_pkt_num),
1334e54fbbdfSXue Chaojing HINIC_PORT_STAT(mac_tx_from_app_bad_pkt_num),
1335e54fbbdfSXue Chaojing };
1336e54fbbdfSXue Chaojing
1337e54fbbdfSXue Chaojing #define HINIC_TXQ_STAT(_stat_item) { \
1338e54fbbdfSXue Chaojing .name = "txq%d_"#_stat_item, \
1339c593642cSPankaj Bharadiya .size = sizeof_field(struct hinic_txq_stats, _stat_item), \
1340e54fbbdfSXue Chaojing .offset = offsetof(struct hinic_txq_stats, _stat_item) \
1341e54fbbdfSXue Chaojing }
1342e54fbbdfSXue Chaojing
1343e54fbbdfSXue Chaojing static struct hinic_stats hinic_tx_queue_stats[] = {
1344e54fbbdfSXue Chaojing HINIC_TXQ_STAT(pkts),
1345e54fbbdfSXue Chaojing HINIC_TXQ_STAT(bytes),
1346e54fbbdfSXue Chaojing HINIC_TXQ_STAT(tx_busy),
1347e54fbbdfSXue Chaojing HINIC_TXQ_STAT(tx_wake),
1348e54fbbdfSXue Chaojing HINIC_TXQ_STAT(tx_dropped),
1349e54fbbdfSXue Chaojing HINIC_TXQ_STAT(big_frags_pkts),
1350e54fbbdfSXue Chaojing };
1351e54fbbdfSXue Chaojing
1352e54fbbdfSXue Chaojing #define HINIC_RXQ_STAT(_stat_item) { \
1353e54fbbdfSXue Chaojing .name = "rxq%d_"#_stat_item, \
1354c593642cSPankaj Bharadiya .size = sizeof_field(struct hinic_rxq_stats, _stat_item), \
1355e54fbbdfSXue Chaojing .offset = offsetof(struct hinic_rxq_stats, _stat_item) \
1356e54fbbdfSXue Chaojing }
1357e54fbbdfSXue Chaojing
1358e54fbbdfSXue Chaojing static struct hinic_stats hinic_rx_queue_stats[] = {
1359e54fbbdfSXue Chaojing HINIC_RXQ_STAT(pkts),
1360e54fbbdfSXue Chaojing HINIC_RXQ_STAT(bytes),
1361e54fbbdfSXue Chaojing HINIC_RXQ_STAT(errors),
1362e54fbbdfSXue Chaojing HINIC_RXQ_STAT(csum_errors),
1363e54fbbdfSXue Chaojing HINIC_RXQ_STAT(other_errors),
1364e54fbbdfSXue Chaojing };
1365e54fbbdfSXue Chaojing
get_drv_queue_stats(struct hinic_dev * nic_dev,u64 * data)1366e54fbbdfSXue Chaojing static void get_drv_queue_stats(struct hinic_dev *nic_dev, u64 *data)
1367e54fbbdfSXue Chaojing {
1368e54fbbdfSXue Chaojing struct hinic_txq_stats txq_stats;
1369e54fbbdfSXue Chaojing struct hinic_rxq_stats rxq_stats;
1370e54fbbdfSXue Chaojing u16 i = 0, j = 0, qid = 0;
1371e54fbbdfSXue Chaojing char *p;
1372e54fbbdfSXue Chaojing
1373e54fbbdfSXue Chaojing for (qid = 0; qid < nic_dev->num_qps; qid++) {
1374e54fbbdfSXue Chaojing if (!nic_dev->txqs)
1375e54fbbdfSXue Chaojing break;
1376e54fbbdfSXue Chaojing
1377e54fbbdfSXue Chaojing hinic_txq_get_stats(&nic_dev->txqs[qid], &txq_stats);
13789ed94117SGuo Zhengkui for (j = 0; j < ARRAY_SIZE(hinic_tx_queue_stats); j++, i++) {
1379e54fbbdfSXue Chaojing p = (char *)&txq_stats +
1380e54fbbdfSXue Chaojing hinic_tx_queue_stats[j].offset;
1381e54fbbdfSXue Chaojing data[i] = (hinic_tx_queue_stats[j].size ==
1382e54fbbdfSXue Chaojing sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
1383e54fbbdfSXue Chaojing }
1384e54fbbdfSXue Chaojing }
1385e54fbbdfSXue Chaojing
1386e54fbbdfSXue Chaojing for (qid = 0; qid < nic_dev->num_qps; qid++) {
1387e54fbbdfSXue Chaojing if (!nic_dev->rxqs)
1388e54fbbdfSXue Chaojing break;
1389e54fbbdfSXue Chaojing
1390e54fbbdfSXue Chaojing hinic_rxq_get_stats(&nic_dev->rxqs[qid], &rxq_stats);
13919ed94117SGuo Zhengkui for (j = 0; j < ARRAY_SIZE(hinic_rx_queue_stats); j++, i++) {
1392e54fbbdfSXue Chaojing p = (char *)&rxq_stats +
1393e54fbbdfSXue Chaojing hinic_rx_queue_stats[j].offset;
1394e54fbbdfSXue Chaojing data[i] = (hinic_rx_queue_stats[j].size ==
1395e54fbbdfSXue Chaojing sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
1396e54fbbdfSXue Chaojing }
1397e54fbbdfSXue Chaojing }
1398e54fbbdfSXue Chaojing }
1399e54fbbdfSXue Chaojing
hinic_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)1400e54fbbdfSXue Chaojing static void hinic_get_ethtool_stats(struct net_device *netdev,
1401e54fbbdfSXue Chaojing struct ethtool_stats *stats, u64 *data)
1402e54fbbdfSXue Chaojing {
1403e54fbbdfSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
1404e54fbbdfSXue Chaojing struct hinic_vport_stats vport_stats = {0};
1405e54fbbdfSXue Chaojing struct hinic_phy_port_stats *port_stats;
1406e54fbbdfSXue Chaojing u16 i = 0, j = 0;
1407e54fbbdfSXue Chaojing char *p;
1408e54fbbdfSXue Chaojing int err;
1409e54fbbdfSXue Chaojing
1410e54fbbdfSXue Chaojing err = hinic_get_vport_stats(nic_dev, &vport_stats);
1411e54fbbdfSXue Chaojing if (err)
1412e54fbbdfSXue Chaojing netif_err(nic_dev, drv, netdev,
1413e54fbbdfSXue Chaojing "Failed to get vport stats from firmware\n");
1414e54fbbdfSXue Chaojing
14159ed94117SGuo Zhengkui for (j = 0; j < ARRAY_SIZE(hinic_function_stats); j++, i++) {
1416e54fbbdfSXue Chaojing p = (char *)&vport_stats + hinic_function_stats[j].offset;
1417e54fbbdfSXue Chaojing data[i] = (hinic_function_stats[j].size ==
1418e54fbbdfSXue Chaojing sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
1419e54fbbdfSXue Chaojing }
1420e54fbbdfSXue Chaojing
1421e54fbbdfSXue Chaojing port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
1422e54fbbdfSXue Chaojing if (!port_stats) {
1423e54fbbdfSXue Chaojing memset(&data[i], 0,
14249ed94117SGuo Zhengkui ARRAY_SIZE(hinic_port_stats) * sizeof(*data));
14259ed94117SGuo Zhengkui i += ARRAY_SIZE(hinic_port_stats);
1426e54fbbdfSXue Chaojing goto get_drv_stats;
1427e54fbbdfSXue Chaojing }
1428e54fbbdfSXue Chaojing
1429e54fbbdfSXue Chaojing err = hinic_get_phy_port_stats(nic_dev, port_stats);
1430e54fbbdfSXue Chaojing if (err)
1431e54fbbdfSXue Chaojing netif_err(nic_dev, drv, netdev,
1432e54fbbdfSXue Chaojing "Failed to get port stats from firmware\n");
1433e54fbbdfSXue Chaojing
14349ed94117SGuo Zhengkui for (j = 0; j < ARRAY_SIZE(hinic_port_stats); j++, i++) {
1435e54fbbdfSXue Chaojing p = (char *)port_stats + hinic_port_stats[j].offset;
1436e54fbbdfSXue Chaojing data[i] = (hinic_port_stats[j].size ==
1437e54fbbdfSXue Chaojing sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
1438e54fbbdfSXue Chaojing }
1439e54fbbdfSXue Chaojing
1440e54fbbdfSXue Chaojing kfree(port_stats);
1441e54fbbdfSXue Chaojing
1442e54fbbdfSXue Chaojing get_drv_stats:
1443e54fbbdfSXue Chaojing get_drv_queue_stats(nic_dev, data + i);
1444e54fbbdfSXue Chaojing }
1445e54fbbdfSXue Chaojing
hinic_get_sset_count(struct net_device * netdev,int sset)1446e54fbbdfSXue Chaojing static int hinic_get_sset_count(struct net_device *netdev, int sset)
1447e54fbbdfSXue Chaojing {
1448e54fbbdfSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
1449e54fbbdfSXue Chaojing int count, q_num;
1450e54fbbdfSXue Chaojing
1451e54fbbdfSXue Chaojing switch (sset) {
14524aa218a4SLuo bin case ETH_SS_TEST:
14539ed94117SGuo Zhengkui return ARRAY_SIZE(hinic_test_strings);
1454e54fbbdfSXue Chaojing case ETH_SS_STATS:
1455e54fbbdfSXue Chaojing q_num = nic_dev->num_qps;
14569ed94117SGuo Zhengkui count = ARRAY_SIZE(hinic_function_stats) +
14579ed94117SGuo Zhengkui (ARRAY_SIZE(hinic_tx_queue_stats) +
14589ed94117SGuo Zhengkui ARRAY_SIZE(hinic_rx_queue_stats)) * q_num;
1459e54fbbdfSXue Chaojing
14609ed94117SGuo Zhengkui count += ARRAY_SIZE(hinic_port_stats);
1461e54fbbdfSXue Chaojing
1462e54fbbdfSXue Chaojing return count;
1463e54fbbdfSXue Chaojing default:
1464e54fbbdfSXue Chaojing return -EOPNOTSUPP;
1465e54fbbdfSXue Chaojing }
1466e54fbbdfSXue Chaojing }
1467e54fbbdfSXue Chaojing
hinic_get_strings(struct net_device * netdev,u32 stringset,u8 * data)1468e54fbbdfSXue Chaojing static void hinic_get_strings(struct net_device *netdev,
1469e54fbbdfSXue Chaojing u32 stringset, u8 *data)
1470e54fbbdfSXue Chaojing {
1471e54fbbdfSXue Chaojing struct hinic_dev *nic_dev = netdev_priv(netdev);
1472e54fbbdfSXue Chaojing char *p = (char *)data;
1473e54fbbdfSXue Chaojing u16 i, j;
1474e54fbbdfSXue Chaojing
1475e54fbbdfSXue Chaojing switch (stringset) {
14764aa218a4SLuo bin case ETH_SS_TEST:
14774aa218a4SLuo bin memcpy(data, *hinic_test_strings, sizeof(hinic_test_strings));
14784aa218a4SLuo bin return;
1479e54fbbdfSXue Chaojing case ETH_SS_STATS:
14809ed94117SGuo Zhengkui for (i = 0; i < ARRAY_SIZE(hinic_function_stats); i++) {
1481e54fbbdfSXue Chaojing memcpy(p, hinic_function_stats[i].name,
1482e54fbbdfSXue Chaojing ETH_GSTRING_LEN);
1483e54fbbdfSXue Chaojing p += ETH_GSTRING_LEN;
1484e54fbbdfSXue Chaojing }
1485e54fbbdfSXue Chaojing
14869ed94117SGuo Zhengkui for (i = 0; i < ARRAY_SIZE(hinic_port_stats); i++) {
1487e54fbbdfSXue Chaojing memcpy(p, hinic_port_stats[i].name,
1488e54fbbdfSXue Chaojing ETH_GSTRING_LEN);
1489e54fbbdfSXue Chaojing p += ETH_GSTRING_LEN;
1490e54fbbdfSXue Chaojing }
1491e54fbbdfSXue Chaojing
1492e54fbbdfSXue Chaojing for (i = 0; i < nic_dev->num_qps; i++) {
14939ed94117SGuo Zhengkui for (j = 0; j < ARRAY_SIZE(hinic_tx_queue_stats); j++) {
1494e54fbbdfSXue Chaojing sprintf(p, hinic_tx_queue_stats[j].name, i);
1495e54fbbdfSXue Chaojing p += ETH_GSTRING_LEN;
1496e54fbbdfSXue Chaojing }
1497e54fbbdfSXue Chaojing }
1498e54fbbdfSXue Chaojing
1499e54fbbdfSXue Chaojing for (i = 0; i < nic_dev->num_qps; i++) {
15009ed94117SGuo Zhengkui for (j = 0; j < ARRAY_SIZE(hinic_rx_queue_stats); j++) {
1501e54fbbdfSXue Chaojing sprintf(p, hinic_rx_queue_stats[j].name, i);
1502e54fbbdfSXue Chaojing p += ETH_GSTRING_LEN;
1503e54fbbdfSXue Chaojing }
1504e54fbbdfSXue Chaojing }
1505e54fbbdfSXue Chaojing
1506e54fbbdfSXue Chaojing return;
1507e54fbbdfSXue Chaojing default:
1508e54fbbdfSXue Chaojing return;
1509e54fbbdfSXue Chaojing }
1510e54fbbdfSXue Chaojing }
1511e54fbbdfSXue Chaojing
hinic_run_lp_test(struct hinic_dev * nic_dev,u32 test_time)15124aa218a4SLuo bin static int hinic_run_lp_test(struct hinic_dev *nic_dev, u32 test_time)
15134aa218a4SLuo bin {
15144aa218a4SLuo bin u8 *lb_test_rx_buf = nic_dev->lb_test_rx_buf;
15154aa218a4SLuo bin struct net_device *netdev = nic_dev->netdev;
15164aa218a4SLuo bin struct sk_buff *skb_tmp = NULL;
15174aa218a4SLuo bin struct sk_buff *skb = NULL;
15184aa218a4SLuo bin u32 cnt = test_time * 5;
15194aa218a4SLuo bin u8 *test_data = NULL;
15204aa218a4SLuo bin u32 i;
15214aa218a4SLuo bin u8 j;
15224aa218a4SLuo bin
15234aa218a4SLuo bin skb_tmp = alloc_skb(LP_PKT_LEN, GFP_ATOMIC);
15244aa218a4SLuo bin if (!skb_tmp)
15254aa218a4SLuo bin return -ENOMEM;
15264aa218a4SLuo bin
15274aa218a4SLuo bin test_data = __skb_put(skb_tmp, LP_PKT_LEN);
15284aa218a4SLuo bin
15294aa218a4SLuo bin memset(test_data, 0xFF, 2 * ETH_ALEN);
15304aa218a4SLuo bin test_data[ETH_ALEN] = 0xFE;
15314aa218a4SLuo bin test_data[2 * ETH_ALEN] = 0x08;
15324aa218a4SLuo bin test_data[2 * ETH_ALEN + 1] = 0x0;
15334aa218a4SLuo bin
15344aa218a4SLuo bin for (i = ETH_HLEN; i < LP_PKT_LEN; i++)
15354aa218a4SLuo bin test_data[i] = i & 0xFF;
15364aa218a4SLuo bin
15374aa218a4SLuo bin skb_tmp->queue_mapping = 0;
15384aa218a4SLuo bin skb_tmp->ip_summed = CHECKSUM_COMPLETE;
15394aa218a4SLuo bin skb_tmp->dev = netdev;
15404aa218a4SLuo bin
15414aa218a4SLuo bin for (i = 0; i < cnt; i++) {
15424aa218a4SLuo bin nic_dev->lb_test_rx_idx = 0;
15434aa218a4SLuo bin memset(lb_test_rx_buf, 0, LP_PKT_CNT * LP_PKT_LEN);
15444aa218a4SLuo bin
15454aa218a4SLuo bin for (j = 0; j < LP_PKT_CNT; j++) {
15464aa218a4SLuo bin skb = pskb_copy(skb_tmp, GFP_ATOMIC);
15474aa218a4SLuo bin if (!skb) {
15484aa218a4SLuo bin dev_kfree_skb_any(skb_tmp);
15494aa218a4SLuo bin netif_err(nic_dev, drv, netdev,
15504aa218a4SLuo bin "Copy skb failed for loopback test\n");
15514aa218a4SLuo bin return -ENOMEM;
15524aa218a4SLuo bin }
15534aa218a4SLuo bin
15544aa218a4SLuo bin /* mark index for every pkt */
15554aa218a4SLuo bin skb->data[LP_PKT_LEN - 1] = j;
15564aa218a4SLuo bin
15574aa218a4SLuo bin if (hinic_lb_xmit_frame(skb, netdev)) {
15584aa218a4SLuo bin dev_kfree_skb_any(skb);
15594aa218a4SLuo bin dev_kfree_skb_any(skb_tmp);
15604aa218a4SLuo bin netif_err(nic_dev, drv, netdev,
15614aa218a4SLuo bin "Xmit pkt failed for loopback test\n");
15624aa218a4SLuo bin return -EBUSY;
15634aa218a4SLuo bin }
15644aa218a4SLuo bin }
15654aa218a4SLuo bin
15664aa218a4SLuo bin /* wait till all pkts received to RX buffer */
15674aa218a4SLuo bin msleep(200);
15684aa218a4SLuo bin
15694aa218a4SLuo bin for (j = 0; j < LP_PKT_CNT; j++) {
15704aa218a4SLuo bin if (memcmp(lb_test_rx_buf + j * LP_PKT_LEN,
15714aa218a4SLuo bin skb_tmp->data, LP_PKT_LEN - 1) ||
15724aa218a4SLuo bin (*(lb_test_rx_buf + j * LP_PKT_LEN +
15734aa218a4SLuo bin LP_PKT_LEN - 1) != j)) {
15744aa218a4SLuo bin dev_kfree_skb_any(skb_tmp);
15754aa218a4SLuo bin netif_err(nic_dev, drv, netdev,
15764aa218a4SLuo bin "Compare pkt failed in loopback test(index=0x%02x, data[%d]=0x%02x)\n",
15774aa218a4SLuo bin j + i * LP_PKT_CNT,
15784aa218a4SLuo bin LP_PKT_LEN - 1,
15794aa218a4SLuo bin *(lb_test_rx_buf + j * LP_PKT_LEN +
15804aa218a4SLuo bin LP_PKT_LEN - 1));
15814aa218a4SLuo bin return -EIO;
15824aa218a4SLuo bin }
15834aa218a4SLuo bin }
15844aa218a4SLuo bin }
15854aa218a4SLuo bin
15864aa218a4SLuo bin dev_kfree_skb_any(skb_tmp);
15874aa218a4SLuo bin return 0;
15884aa218a4SLuo bin }
15894aa218a4SLuo bin
do_lp_test(struct hinic_dev * nic_dev,u32 flags,u32 test_time,enum diag_test_index * test_index)15904aa218a4SLuo bin static int do_lp_test(struct hinic_dev *nic_dev, u32 flags, u32 test_time,
15914aa218a4SLuo bin enum diag_test_index *test_index)
15924aa218a4SLuo bin {
15934aa218a4SLuo bin struct net_device *netdev = nic_dev->netdev;
15944aa218a4SLuo bin u8 *lb_test_rx_buf = NULL;
15954aa218a4SLuo bin int err = 0;
15964aa218a4SLuo bin
15974aa218a4SLuo bin if (!(flags & ETH_TEST_FL_EXTERNAL_LB)) {
15984aa218a4SLuo bin *test_index = INTERNAL_LP_TEST;
15994aa218a4SLuo bin if (hinic_set_loopback_mode(nic_dev->hwdev,
16004aa218a4SLuo bin HINIC_INTERNAL_LP_MODE, true)) {
16014aa218a4SLuo bin netif_err(nic_dev, drv, netdev,
16024aa218a4SLuo bin "Failed to set port loopback mode before loopback test\n");
16034aa218a4SLuo bin return -EIO;
16044aa218a4SLuo bin }
16054aa218a4SLuo bin } else {
16064aa218a4SLuo bin *test_index = EXTERNAL_LP_TEST;
16074aa218a4SLuo bin }
16084aa218a4SLuo bin
16094aa218a4SLuo bin lb_test_rx_buf = vmalloc(LP_PKT_CNT * LP_PKT_LEN);
16104aa218a4SLuo bin if (!lb_test_rx_buf) {
16114aa218a4SLuo bin err = -ENOMEM;
16124aa218a4SLuo bin } else {
16134aa218a4SLuo bin nic_dev->lb_test_rx_buf = lb_test_rx_buf;
16144aa218a4SLuo bin nic_dev->lb_pkt_len = LP_PKT_LEN;
16154aa218a4SLuo bin nic_dev->flags |= HINIC_LP_TEST;
16164aa218a4SLuo bin err = hinic_run_lp_test(nic_dev, test_time);
16174aa218a4SLuo bin nic_dev->flags &= ~HINIC_LP_TEST;
16184aa218a4SLuo bin msleep(100);
16194aa218a4SLuo bin vfree(lb_test_rx_buf);
16204aa218a4SLuo bin nic_dev->lb_test_rx_buf = NULL;
16214aa218a4SLuo bin }
16224aa218a4SLuo bin
16234aa218a4SLuo bin if (!(flags & ETH_TEST_FL_EXTERNAL_LB)) {
16244aa218a4SLuo bin if (hinic_set_loopback_mode(nic_dev->hwdev,
16254aa218a4SLuo bin HINIC_INTERNAL_LP_MODE, false)) {
16264aa218a4SLuo bin netif_err(nic_dev, drv, netdev,
16274aa218a4SLuo bin "Failed to cancel port loopback mode after loopback test\n");
16284aa218a4SLuo bin err = -EIO;
16294aa218a4SLuo bin }
16304aa218a4SLuo bin }
16314aa218a4SLuo bin
16324aa218a4SLuo bin return err;
16334aa218a4SLuo bin }
16344aa218a4SLuo bin
hinic_diag_test(struct net_device * netdev,struct ethtool_test * eth_test,u64 * data)16354aa218a4SLuo bin static void hinic_diag_test(struct net_device *netdev,
16364aa218a4SLuo bin struct ethtool_test *eth_test, u64 *data)
16374aa218a4SLuo bin {
16384aa218a4SLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
16394aa218a4SLuo bin enum hinic_port_link_state link_state;
16404aa218a4SLuo bin enum diag_test_index test_index = 0;
16414aa218a4SLuo bin int err = 0;
16424aa218a4SLuo bin
16434aa218a4SLuo bin memset(data, 0, DIAG_TEST_MAX * sizeof(u64));
16444aa218a4SLuo bin
16454aa218a4SLuo bin /* don't support loopback test when netdev is closed. */
16464aa218a4SLuo bin if (!(nic_dev->flags & HINIC_INTF_UP)) {
16474aa218a4SLuo bin netif_err(nic_dev, drv, netdev,
16484aa218a4SLuo bin "Do not support loopback test when netdev is closed\n");
16494aa218a4SLuo bin eth_test->flags |= ETH_TEST_FL_FAILED;
16504aa218a4SLuo bin data[PORT_DOWN_ERR_IDX] = 1;
16514aa218a4SLuo bin return;
16524aa218a4SLuo bin }
16534aa218a4SLuo bin
16544aa218a4SLuo bin netif_carrier_off(netdev);
1655fc25fa97SLuo bin netif_tx_disable(netdev);
16564aa218a4SLuo bin
16574aa218a4SLuo bin err = do_lp_test(nic_dev, eth_test->flags, LP_DEFAULT_TIME,
16584aa218a4SLuo bin &test_index);
16594aa218a4SLuo bin if (err) {
16604aa218a4SLuo bin eth_test->flags |= ETH_TEST_FL_FAILED;
16614aa218a4SLuo bin data[test_index] = 1;
16624aa218a4SLuo bin }
16634aa218a4SLuo bin
1664fc25fa97SLuo bin netif_tx_wake_all_queues(netdev);
1665fc25fa97SLuo bin
16664aa218a4SLuo bin err = hinic_port_link_state(nic_dev, &link_state);
16674aa218a4SLuo bin if (!err && link_state == HINIC_LINK_STATE_UP)
16684aa218a4SLuo bin netif_carrier_on(netdev);
16694aa218a4SLuo bin }
16704aa218a4SLuo bin
hinic_set_phys_id(struct net_device * netdev,enum ethtool_phys_id_state state)167107afcc7aSLuo bin static int hinic_set_phys_id(struct net_device *netdev,
167207afcc7aSLuo bin enum ethtool_phys_id_state state)
167307afcc7aSLuo bin {
167407afcc7aSLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
167507afcc7aSLuo bin int err = 0;
167607afcc7aSLuo bin u8 port;
167707afcc7aSLuo bin
167807afcc7aSLuo bin port = nic_dev->hwdev->port_id;
167907afcc7aSLuo bin
168007afcc7aSLuo bin switch (state) {
168107afcc7aSLuo bin case ETHTOOL_ID_ACTIVE:
168207afcc7aSLuo bin err = hinic_set_led_status(nic_dev->hwdev, port,
168307afcc7aSLuo bin HINIC_LED_TYPE_LINK,
168407afcc7aSLuo bin HINIC_LED_MODE_FORCE_2HZ);
168507afcc7aSLuo bin if (err)
168607afcc7aSLuo bin netif_err(nic_dev, drv, netdev,
168707afcc7aSLuo bin "Set LED blinking in 2HZ failed\n");
168807afcc7aSLuo bin break;
168907afcc7aSLuo bin
169007afcc7aSLuo bin case ETHTOOL_ID_INACTIVE:
169107afcc7aSLuo bin err = hinic_reset_led_status(nic_dev->hwdev, port);
169207afcc7aSLuo bin if (err)
169307afcc7aSLuo bin netif_err(nic_dev, drv, netdev,
169407afcc7aSLuo bin "Reset LED to original status failed\n");
169507afcc7aSLuo bin break;
169607afcc7aSLuo bin
169707afcc7aSLuo bin default:
169807afcc7aSLuo bin return -EOPNOTSUPP;
169907afcc7aSLuo bin }
170007afcc7aSLuo bin
170107afcc7aSLuo bin return err;
170207afcc7aSLuo bin }
170307afcc7aSLuo bin
hinic_get_module_info(struct net_device * netdev,struct ethtool_modinfo * modinfo)17042ac84cd1SLuo bin static int hinic_get_module_info(struct net_device *netdev,
17052ac84cd1SLuo bin struct ethtool_modinfo *modinfo)
17062ac84cd1SLuo bin {
17072ac84cd1SLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
17082ac84cd1SLuo bin u8 sfp_type_ext;
17092ac84cd1SLuo bin u8 sfp_type;
17102ac84cd1SLuo bin int err;
17112ac84cd1SLuo bin
17122ac84cd1SLuo bin err = hinic_get_sfp_type(nic_dev->hwdev, &sfp_type, &sfp_type_ext);
17132ac84cd1SLuo bin if (err)
17142ac84cd1SLuo bin return err;
17152ac84cd1SLuo bin
17162ac84cd1SLuo bin switch (sfp_type) {
17172ac84cd1SLuo bin case SFF8024_ID_SFP:
17182ac84cd1SLuo bin modinfo->type = ETH_MODULE_SFF_8472;
17192ac84cd1SLuo bin modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
17202ac84cd1SLuo bin break;
17212ac84cd1SLuo bin case SFF8024_ID_QSFP_8438:
17222ac84cd1SLuo bin modinfo->type = ETH_MODULE_SFF_8436;
17232ac84cd1SLuo bin modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
17242ac84cd1SLuo bin break;
17252ac84cd1SLuo bin case SFF8024_ID_QSFP_8436_8636:
17262ac84cd1SLuo bin if (sfp_type_ext >= 0x3) {
17272ac84cd1SLuo bin modinfo->type = ETH_MODULE_SFF_8636;
17282ac84cd1SLuo bin modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
17292ac84cd1SLuo bin
17302ac84cd1SLuo bin } else {
17312ac84cd1SLuo bin modinfo->type = ETH_MODULE_SFF_8436;
17322ac84cd1SLuo bin modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
17332ac84cd1SLuo bin }
17342ac84cd1SLuo bin break;
17352ac84cd1SLuo bin case SFF8024_ID_QSFP28_8636:
17362ac84cd1SLuo bin modinfo->type = ETH_MODULE_SFF_8636;
17372ac84cd1SLuo bin modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
17382ac84cd1SLuo bin break;
17392ac84cd1SLuo bin default:
17402ac84cd1SLuo bin netif_warn(nic_dev, drv, netdev,
17412ac84cd1SLuo bin "Optical module unknown: 0x%x\n", sfp_type);
17422ac84cd1SLuo bin return -EINVAL;
17432ac84cd1SLuo bin }
17442ac84cd1SLuo bin
17452ac84cd1SLuo bin return 0;
17462ac84cd1SLuo bin }
17472ac84cd1SLuo bin
hinic_get_module_eeprom(struct net_device * netdev,struct ethtool_eeprom * ee,u8 * data)17482ac84cd1SLuo bin static int hinic_get_module_eeprom(struct net_device *netdev,
17492ac84cd1SLuo bin struct ethtool_eeprom *ee, u8 *data)
17502ac84cd1SLuo bin {
17512ac84cd1SLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
17522ac84cd1SLuo bin u8 sfp_data[STD_SFP_INFO_MAX_SIZE];
17532ac84cd1SLuo bin u16 len;
17542ac84cd1SLuo bin int err;
17552ac84cd1SLuo bin
17562ac84cd1SLuo bin if (!ee->len || ((ee->len + ee->offset) > STD_SFP_INFO_MAX_SIZE))
17572ac84cd1SLuo bin return -EINVAL;
17582ac84cd1SLuo bin
17592ac84cd1SLuo bin memset(data, 0, ee->len);
17602ac84cd1SLuo bin
17612ac84cd1SLuo bin err = hinic_get_sfp_eeprom(nic_dev->hwdev, sfp_data, &len);
17622ac84cd1SLuo bin if (err)
17632ac84cd1SLuo bin return err;
17642ac84cd1SLuo bin
17652ac84cd1SLuo bin memcpy(data, sfp_data + ee->offset, ee->len);
17662ac84cd1SLuo bin
17672ac84cd1SLuo bin return 0;
17682ac84cd1SLuo bin }
17692ac84cd1SLuo bin
1770c15850c7SLuo bin static int
hinic_get_link_ext_state(struct net_device * netdev,struct ethtool_link_ext_state_info * link_ext_state_info)1771c15850c7SLuo bin hinic_get_link_ext_state(struct net_device *netdev,
1772c15850c7SLuo bin struct ethtool_link_ext_state_info *link_ext_state_info)
1773c15850c7SLuo bin {
1774c15850c7SLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
1775c15850c7SLuo bin
1776c15850c7SLuo bin if (netif_carrier_ok(netdev))
1777c15850c7SLuo bin return -ENODATA;
1778c15850c7SLuo bin
1779c15850c7SLuo bin if (nic_dev->cable_unplugged)
1780c15850c7SLuo bin link_ext_state_info->link_ext_state =
1781c15850c7SLuo bin ETHTOOL_LINK_EXT_STATE_NO_CABLE;
1782c15850c7SLuo bin else if (nic_dev->module_unrecognized)
1783c15850c7SLuo bin link_ext_state_info->link_ext_state =
1784c15850c7SLuo bin ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH;
1785c15850c7SLuo bin
1786c15850c7SLuo bin return 0;
1787c15850c7SLuo bin }
1788c15850c7SLuo bin
1789eb8ce9acSXue Chaojing static const struct ethtool_ops hinic_ethtool_ops = {
1790a0337c0dSLuo bin .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
1791a0337c0dSLuo bin ETHTOOL_COALESCE_RX_MAX_FRAMES |
1792a0337c0dSLuo bin ETHTOOL_COALESCE_TX_USECS |
1793a0337c0dSLuo bin ETHTOOL_COALESCE_TX_MAX_FRAMES,
1794a0337c0dSLuo bin
1795eb8ce9acSXue Chaojing .get_link_ksettings = hinic_get_link_ksettings,
179601f2b3daSLuo bin .set_link_ksettings = hinic_set_link_ksettings,
1797eb8ce9acSXue Chaojing .get_drvinfo = hinic_get_drvinfo,
1798eb8ce9acSXue Chaojing .get_link = ethtool_op_get_link,
1799c15850c7SLuo bin .get_link_ext_state = hinic_get_link_ext_state,
1800eb8ce9acSXue Chaojing .get_ringparam = hinic_get_ringparam,
1801bcab6782SLuo bin .set_ringparam = hinic_set_ringparam,
1802a0337c0dSLuo bin .get_coalesce = hinic_get_coalesce,
1803a0337c0dSLuo bin .set_coalesce = hinic_set_coalesce,
1804a0337c0dSLuo bin .get_per_queue_coalesce = hinic_get_per_queue_coalesce,
1805a0337c0dSLuo bin .set_per_queue_coalesce = hinic_set_per_queue_coalesce,
1806ea256222SLuo bin .get_pauseparam = hinic_get_pauseparam,
1807ea256222SLuo bin .set_pauseparam = hinic_set_pauseparam,
1808ea256222SLuo bin .get_channels = hinic_get_channels,
1809ea256222SLuo bin .set_channels = hinic_set_channels,
1810ea256222SLuo bin .get_rxnfc = hinic_get_rxnfc,
1811ea256222SLuo bin .set_rxnfc = hinic_set_rxnfc,
1812ea256222SLuo bin .get_rxfh_key_size = hinic_get_rxfh_key_size,
1813ea256222SLuo bin .get_rxfh_indir_size = hinic_get_rxfh_indir_size,
1814ea256222SLuo bin .get_rxfh = hinic_get_rxfh,
1815ea256222SLuo bin .set_rxfh = hinic_set_rxfh,
1816ea256222SLuo bin .get_sset_count = hinic_get_sset_count,
1817ea256222SLuo bin .get_ethtool_stats = hinic_get_ethtool_stats,
1818ea256222SLuo bin .get_strings = hinic_get_strings,
18194aa218a4SLuo bin .self_test = hinic_diag_test,
182007afcc7aSLuo bin .set_phys_id = hinic_set_phys_id,
18212ac84cd1SLuo bin .get_module_info = hinic_get_module_info,
18222ac84cd1SLuo bin .get_module_eeprom = hinic_get_module_eeprom,
1823ea256222SLuo bin };
1824ea256222SLuo bin
1825ea256222SLuo bin static const struct ethtool_ops hinicvf_ethtool_ops = {
1826a0337c0dSLuo bin .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
1827a0337c0dSLuo bin ETHTOOL_COALESCE_RX_MAX_FRAMES |
1828a0337c0dSLuo bin ETHTOOL_COALESCE_TX_USECS |
1829a0337c0dSLuo bin ETHTOOL_COALESCE_TX_MAX_FRAMES,
1830a0337c0dSLuo bin
1831ea256222SLuo bin .get_link_ksettings = hinic_get_link_ksettings,
1832ea256222SLuo bin .get_drvinfo = hinic_get_drvinfo,
1833ea256222SLuo bin .get_link = ethtool_op_get_link,
1834ea256222SLuo bin .get_ringparam = hinic_get_ringparam,
1835ea256222SLuo bin .set_ringparam = hinic_set_ringparam,
1836a0337c0dSLuo bin .get_coalesce = hinic_get_coalesce,
1837a0337c0dSLuo bin .set_coalesce = hinic_set_coalesce,
1838a0337c0dSLuo bin .get_per_queue_coalesce = hinic_get_per_queue_coalesce,
1839a0337c0dSLuo bin .set_per_queue_coalesce = hinic_set_per_queue_coalesce,
1840eb8ce9acSXue Chaojing .get_channels = hinic_get_channels,
18412eed5a8bSLuo bin .set_channels = hinic_set_channels,
18424fdc51bbSXue Chaojing .get_rxnfc = hinic_get_rxnfc,
18434fdc51bbSXue Chaojing .set_rxnfc = hinic_set_rxnfc,
18444fdc51bbSXue Chaojing .get_rxfh_key_size = hinic_get_rxfh_key_size,
18454fdc51bbSXue Chaojing .get_rxfh_indir_size = hinic_get_rxfh_indir_size,
18464fdc51bbSXue Chaojing .get_rxfh = hinic_get_rxfh,
18474fdc51bbSXue Chaojing .set_rxfh = hinic_set_rxfh,
1848e54fbbdfSXue Chaojing .get_sset_count = hinic_get_sset_count,
1849e54fbbdfSXue Chaojing .get_ethtool_stats = hinic_get_ethtool_stats,
1850e54fbbdfSXue Chaojing .get_strings = hinic_get_strings,
1851eb8ce9acSXue Chaojing };
1852eb8ce9acSXue Chaojing
hinic_set_ethtool_ops(struct net_device * netdev)1853eb8ce9acSXue Chaojing void hinic_set_ethtool_ops(struct net_device *netdev)
1854eb8ce9acSXue Chaojing {
1855ea256222SLuo bin struct hinic_dev *nic_dev = netdev_priv(netdev);
1856ea256222SLuo bin
1857ea256222SLuo bin if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
1858eb8ce9acSXue Chaojing netdev->ethtool_ops = &hinic_ethtool_ops;
1859ea256222SLuo bin else
1860ea256222SLuo bin netdev->ethtool_ops = &hinicvf_ethtool_ops;
1861eb8ce9acSXue Chaojing }
1862