Commit de9c8a6a authored by David S. Miller's avatar David S. Miller

Merge branch 'hns3-dcb'

Yunsheng Lin says:

====================
Add support for DCB feature in hns3 driver

The patchset contains some enhancement related to DCB before
adding support for DCB feature.

This patchset depends on the following patchset:
https://patchwork.ozlabs.org/cover/815646/
https://patchwork.ozlabs.org/cover/816145/

High Level Architecture:

                   [ lldpad ]
                       |
                       |
                       |
                 [ hns3_dcbnl ]
                       |
                       |
                       |
                 [ hclge_dcb ]
                   /      \
                /            \
             /                  \
     [ hclge_main ]        [ hclge_tm ]

Current patch-set support following functionality:
   Use of lldptool to configure the tc schedule mode, tc
   bandwidth(if schedule mode is ETS), prio_tc_map and
   PFC parameter.

V3: Drop mqprio support

V2: Fix for not defining variables in local loop.

V1: Initial Submit.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6ade97da 9df8f79a
...@@ -103,4 +103,13 @@ config HNS3_ENET ...@@ -103,4 +103,13 @@ config HNS3_ENET
family of SoCs. This module depends upon HNAE3 driver to access the HNAE3 family of SoCs. This module depends upon HNAE3 driver to access the HNAE3
devices and their associated operations. devices and their associated operations.
config HNS3_DCB
bool "Hisilicon HNS3 Data Center Bridge Support"
default n
depends on HNS3 && HNS3_HCLGE && DCB
---help---
Say Y here if you want to use Data Center Bridging (DCB) in the HNS3 driver.
If unsure, say N.
endif # NET_VENDOR_HISILICON endif # NET_VENDOR_HISILICON
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/dcbnl.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -131,6 +132,7 @@ struct hnae3_client_ops { ...@@ -131,6 +132,7 @@ struct hnae3_client_ops {
int (*init_instance)(struct hnae3_handle *handle); int (*init_instance)(struct hnae3_handle *handle);
void (*uninit_instance)(struct hnae3_handle *handle, bool reset); void (*uninit_instance)(struct hnae3_handle *handle, bool reset);
void (*link_status_change)(struct hnae3_handle *handle, bool state); void (*link_status_change)(struct hnae3_handle *handle, bool state);
int (*setup_tc)(struct hnae3_handle *handle, u8 tc);
}; };
#define HNAE3_CLIENT_NAME_LENGTH 16 #define HNAE3_CLIENT_NAME_LENGTH 16
...@@ -363,6 +365,20 @@ struct hnae3_ae_ops { ...@@ -363,6 +365,20 @@ struct hnae3_ae_ops {
u16 vlan, u8 qos, __be16 proto); u16 vlan, u8 qos, __be16 proto);
}; };
struct hnae3_dcb_ops {
/* IEEE 802.1Qaz std */
int (*ieee_getets)(struct hnae3_handle *, struct ieee_ets *);
int (*ieee_setets)(struct hnae3_handle *, struct ieee_ets *);
int (*ieee_getpfc)(struct hnae3_handle *, struct ieee_pfc *);
int (*ieee_setpfc)(struct hnae3_handle *, struct ieee_pfc *);
/* DCBX configuration */
u8 (*getdcbx)(struct hnae3_handle *);
u8 (*setdcbx)(struct hnae3_handle *, u8);
int (*map_update)(struct hnae3_handle *);
};
struct hnae3_ae_algo { struct hnae3_ae_algo {
const struct hnae3_ae_ops *ops; const struct hnae3_ae_ops *ops;
struct list_head node; struct list_head node;
...@@ -394,6 +410,7 @@ struct hnae3_knic_private_info { ...@@ -394,6 +410,7 @@ struct hnae3_knic_private_info {
u16 num_tqps; /* total number of TQPs in this handle */ u16 num_tqps; /* total number of TQPs in this handle */
struct hnae3_queue **tqp; /* array base of all TQPs in this instance */ struct hnae3_queue **tqp; /* array base of all TQPs in this instance */
const struct hnae3_dcb_ops *dcb_ops;
}; };
struct hnae3_roce_private_info { struct hnae3_roce_private_info {
......
...@@ -7,5 +7,9 @@ ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3 ...@@ -7,5 +7,9 @@ ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3
obj-$(CONFIG_HNS3_HCLGE) += hclge.o obj-$(CONFIG_HNS3_HCLGE) += hclge.o
hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o
hclge-$(CONFIG_HNS3_DCB) += hclge_dcb.o
obj-$(CONFIG_HNS3_ENET) += hns3.o obj-$(CONFIG_HNS3_ENET) += hns3.o
hns3-objs = hns3_enet.o hns3_ethtool.o hns3-objs = hns3_enet.o hns3_ethtool.o
hns3-$(CONFIG_HNS3_DCB) += hns3_dcbnl.o
...@@ -311,6 +311,7 @@ struct hclge_tc_thrd { ...@@ -311,6 +311,7 @@ struct hclge_tc_thrd {
struct hclge_priv_buf { struct hclge_priv_buf {
struct hclge_waterline wl; /* Waterline for low and high*/ struct hclge_waterline wl; /* Waterline for low and high*/
u32 buf_size; /* TC private buffer size */ u32 buf_size; /* TC private buffer size */
u32 tx_buf_size;
u32 enable; /* Enable TC private buffer or not */ u32 enable; /* Enable TC private buffer or not */
}; };
...@@ -321,6 +322,11 @@ struct hclge_shared_buf { ...@@ -321,6 +322,11 @@ struct hclge_shared_buf {
u32 buf_size; u32 buf_size;
}; };
struct hclge_pkt_buf_alloc {
struct hclge_priv_buf priv_buf[HCLGE_MAX_TC_NUM];
struct hclge_shared_buf s_buf;
};
#define HCLGE_RX_COM_WL_EN_B 15 #define HCLGE_RX_COM_WL_EN_B 15
struct hclge_rx_com_wl_buf { struct hclge_rx_com_wl_buf {
__le16 high_wl; __le16 high_wl;
......
/*
* Copyright (c) 2016-2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "hclge_main.h"
#include "hclge_tm.h"
#include "hnae3.h"
#define BW_PERCENT 100
static int hclge_ieee_ets_to_tm_info(struct hclge_dev *hdev,
struct ieee_ets *ets)
{
u8 i;
for (i = 0; i < HNAE3_MAX_TC; i++) {
switch (ets->tc_tsa[i]) {
case IEEE_8021QAZ_TSA_STRICT:
hdev->tm_info.tc_info[i].tc_sch_mode =
HCLGE_SCH_MODE_SP;
hdev->tm_info.pg_info[0].tc_dwrr[i] = 0;
break;
case IEEE_8021QAZ_TSA_ETS:
hdev->tm_info.tc_info[i].tc_sch_mode =
HCLGE_SCH_MODE_DWRR;
hdev->tm_info.pg_info[0].tc_dwrr[i] =
ets->tc_tx_bw[i];
break;
default:
/* Hardware only supports SP (strict priority)
* or ETS (enhanced transmission selection)
* algorithms, if we receive some other value
* from dcbnl, then throw an error.
*/
return -EINVAL;
}
}
return hclge_tm_prio_tc_info_update(hdev, ets->prio_tc);
}
static void hclge_tm_info_to_ieee_ets(struct hclge_dev *hdev,
struct ieee_ets *ets)
{
u32 i;
memset(ets, 0, sizeof(*ets));
ets->willing = 1;
ets->ets_cap = hdev->tc_max;
for (i = 0; i < HNAE3_MAX_TC; i++) {
ets->prio_tc[i] = hdev->tm_info.prio_tc[i];
ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
if (hdev->tm_info.tc_info[i].tc_sch_mode ==
HCLGE_SCH_MODE_SP)
ets->tc_tsa[i] = IEEE_8021QAZ_TSA_STRICT;
else
ets->tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
}
}
/* IEEE std */
static int hclge_ieee_getets(struct hnae3_handle *h, struct ieee_ets *ets)
{
struct hclge_vport *vport = hclge_get_vport(h);
struct hclge_dev *hdev = vport->back;
hclge_tm_info_to_ieee_ets(hdev, ets);
return 0;
}
static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets,
u8 *tc, bool *changed)
{
u32 total_ets_bw = 0;
u8 max_tc = 0;
u8 i;
for (i = 0; i < HNAE3_MAX_TC; i++) {
if (ets->prio_tc[i] >= hdev->tc_max ||
i >= hdev->tc_max)
return -EINVAL;
if (ets->prio_tc[i] != hdev->tm_info.prio_tc[i])
*changed = true;
if (ets->prio_tc[i] > max_tc)
max_tc = ets->prio_tc[i];
switch (ets->tc_tsa[i]) {
case IEEE_8021QAZ_TSA_STRICT:
if (hdev->tm_info.tc_info[i].tc_sch_mode !=
HCLGE_SCH_MODE_SP)
*changed = true;
break;
case IEEE_8021QAZ_TSA_ETS:
if (hdev->tm_info.tc_info[i].tc_sch_mode !=
HCLGE_SCH_MODE_DWRR)
*changed = true;
total_ets_bw += ets->tc_tx_bw[i];
break;
default:
return -EINVAL;
}
}
if (total_ets_bw != BW_PERCENT)
return -EINVAL;
*tc = max_tc + 1;
if (*tc != hdev->tm_info.num_tc)
*changed = true;
return 0;
}
static int hclge_map_update(struct hnae3_handle *h)
{
struct hclge_vport *vport = hclge_get_vport(h);
struct hclge_dev *hdev = vport->back;
int ret;
ret = hclge_tm_map_cfg(hdev);
if (ret)
return ret;
ret = hclge_tm_schd_mode_hw(hdev);
if (ret)
return ret;
ret = hclge_pause_setup_hw(hdev);
if (ret)
return ret;
ret = hclge_buffer_alloc(hdev);
if (ret)
return ret;
return hclge_rss_init_hw(hdev);
}
static int hclge_client_setup_tc(struct hclge_dev *hdev)
{
struct hclge_vport *vport = hdev->vport;
struct hnae3_client *client;
struct hnae3_handle *handle;
int ret;
u32 i;
for (i = 0; i < hdev->num_vmdq_vport + 1; i++) {
handle = &vport[i].nic;
client = handle->client;
if (!client || !client->ops || !client->ops->setup_tc)
continue;
ret = client->ops->setup_tc(handle, hdev->tm_info.num_tc);
if (ret)
return ret;
}
return 0;
}
static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)
{
struct hclge_vport *vport = hclge_get_vport(h);
struct hclge_dev *hdev = vport->back;
bool map_changed = false;
u8 num_tc = 0;
int ret;
if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
return -EINVAL;
ret = hclge_ets_validate(hdev, ets, &num_tc, &map_changed);
if (ret)
return ret;
hclge_tm_schd_info_update(hdev, num_tc);
ret = hclge_ieee_ets_to_tm_info(hdev, ets);
if (ret)
return ret;
if (map_changed) {
ret = hclge_client_setup_tc(hdev);
if (ret)
return ret;
}
return hclge_tm_dwrr_cfg(hdev);
}
static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
{
struct hclge_vport *vport = hclge_get_vport(h);
struct hclge_dev *hdev = vport->back;
u8 i, j, pfc_map, *prio_tc;
memset(pfc, 0, sizeof(*pfc));
pfc->pfc_cap = hdev->pfc_max;
prio_tc = hdev->tm_info.prio_tc;
pfc_map = hdev->tm_info.hw_pfc_map;
/* Pfc setting is based on TC */
for (i = 0; i < hdev->tm_info.num_tc; i++) {
for (j = 0; j < HNAE3_MAX_USER_PRIO; j++) {
if ((prio_tc[j] == i) && (pfc_map & BIT(i)))
pfc->pfc_en |= BIT(j);
}
}
return 0;
}
static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
{
struct hclge_vport *vport = hclge_get_vport(h);
struct hclge_dev *hdev = vport->back;
u8 i, j, pfc_map, *prio_tc;
if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
return -EINVAL;
prio_tc = hdev->tm_info.prio_tc;
pfc_map = 0;
for (i = 0; i < hdev->tm_info.num_tc; i++) {
for (j = 0; j < HNAE3_MAX_USER_PRIO; j++) {
if ((prio_tc[j] == i) && (pfc->pfc_en & BIT(j))) {
pfc_map |= BIT(i);
break;
}
}
}
if (pfc_map == hdev->tm_info.hw_pfc_map)
return 0;
hdev->tm_info.hw_pfc_map = pfc_map;
return hclge_pause_setup_hw(hdev);
}
/* DCBX configuration */
static u8 hclge_getdcbx(struct hnae3_handle *h)
{
struct hclge_vport *vport = hclge_get_vport(h);
struct hclge_dev *hdev = vport->back;
return hdev->dcbx_cap;
}
static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode)
{
struct hclge_vport *vport = hclge_get_vport(h);
struct hclge_dev *hdev = vport->back;
/* No support for LLD_MANAGED modes or CEE */
if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
(mode & DCB_CAP_DCBX_VER_CEE) ||
!(mode & DCB_CAP_DCBX_HOST))
return 1;
hdev->dcbx_cap = mode;
return 0;
}
static const struct hnae3_dcb_ops hns3_dcb_ops = {
.ieee_getets = hclge_ieee_getets,
.ieee_setets = hclge_ieee_setets,
.ieee_getpfc = hclge_ieee_getpfc,
.ieee_setpfc = hclge_ieee_setpfc,
.getdcbx = hclge_getdcbx,
.setdcbx = hclge_setdcbx,
.map_update = hclge_map_update,
};
void hclge_dcb_ops_set(struct hclge_dev *hdev)
{
struct hclge_vport *vport = hdev->vport;
struct hnae3_knic_private_info *kinfo;
/* Hdev does not support DCB or vport is
* not a pf, then dcb_ops is not set.
*/
if (!hnae3_dev_dcb_supported(hdev) ||
vport->vport_id != 0)
return;
kinfo = &vport->nic.kinfo;
kinfo->dcb_ops = &hns3_dcb_ops;
hdev->dcbx_cap = DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_HOST;
}
/*
* Copyright (c) 2016~2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __HCLGE_DCB_H__
#define __HCLGE_DCB_H__
#include "hclge_main.h"
#ifdef CONFIG_HNS3_DCB
void hclge_dcb_ops_set(struct hclge_dev *hdev);
#else
static inline void hclge_dcb_ops_set(struct hclge_dev *hdev) {}
#endif
#endif /* __HCLGE_DCB_H__ */
...@@ -421,8 +421,11 @@ struct hclge_dev { ...@@ -421,8 +421,11 @@ struct hclge_dev {
#define HCLGE_FLAG_TC_BASE_SCH_MODE 1 #define HCLGE_FLAG_TC_BASE_SCH_MODE 1
#define HCLGE_FLAG_VNET_BASE_SCH_MODE 2 #define HCLGE_FLAG_VNET_BASE_SCH_MODE 2
u8 tx_sch_mode; u8 tx_sch_mode;
u8 tc_max;
u8 pfc_max;
u8 default_up; u8 default_up;
u8 dcbx_cap;
struct hclge_tm_info tm_info; struct hclge_tm_info tm_info;
u16 num_msi; u16 num_msi;
...@@ -463,8 +466,6 @@ struct hclge_dev { ...@@ -463,8 +466,6 @@ struct hclge_dev {
u32 pkt_buf_size; /* Total pf buf size for tx/rx */ u32 pkt_buf_size; /* Total pf buf size for tx/rx */
u32 mps; /* Max packet size */ u32 mps; /* Max packet size */
struct hclge_priv_buf *priv_buf;
struct hclge_shared_buf s_buf;
enum hclge_mta_dmac_sel_type mta_mac_sel_type; enum hclge_mta_dmac_sel_type mta_mac_sel_type;
bool enable_mta; /* Mutilcast filter enable */ bool enable_mta; /* Mutilcast filter enable */
...@@ -517,4 +518,7 @@ static inline int hclge_get_queue_id(struct hnae3_queue *queue) ...@@ -517,4 +518,7 @@ static inline int hclge_get_queue_id(struct hnae3_queue *queue)
int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex); int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex);
int hclge_set_vf_vlan_common(struct hclge_dev *vport, int vfid, int hclge_set_vf_vlan_common(struct hclge_dev *vport, int vfid,
bool is_kill, u16 vlan, u8 qos, __be16 proto); bool is_kill, u16 vlan, u8 qos, __be16 proto);
int hclge_buffer_alloc(struct hclge_dev *hdev);
int hclge_rss_init_hw(struct hclge_dev *hdev);
#endif #endif
...@@ -124,6 +124,20 @@ static int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx) ...@@ -124,6 +124,20 @@ static int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
return hclge_cmd_send(&hdev->hw, &desc, 1); return hclge_cmd_send(&hdev->hw, &desc, 1);
} }
static int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
u8 pfc_bitmap)
{
struct hclge_desc desc;
struct hclge_pfc_en_cmd *pfc = (struct hclge_pfc_en_cmd *)&desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_PFC_PAUSE_EN, false);
pfc->tx_rx_en_bitmap = tx_rx_bitmap;
pfc->pri_en_bitmap = pfc_bitmap;
return hclge_cmd_send(&hdev->hw, &desc, 1);
}
static int hclge_fill_pri_array(struct hclge_dev *hdev, u8 *pri, u8 pri_id) static int hclge_fill_pri_array(struct hclge_dev *hdev, u8 *pri, u8 pri_id)
{ {
u8 tc; u8 tc;
...@@ -287,6 +301,34 @@ static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev, ...@@ -287,6 +301,34 @@ static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev,
return hclge_cmd_send(&hdev->hw, &desc, 1); return hclge_cmd_send(&hdev->hw, &desc, 1);
} }
static int hclge_tm_port_shaper_cfg(struct hclge_dev *hdev)
{
struct hclge_port_shapping_cmd *shap_cfg_cmd;
struct hclge_desc desc;
u32 shapping_para = 0;
u8 ir_u, ir_b, ir_s;
int ret;
ret = hclge_shaper_para_calc(HCLGE_ETHER_MAX_RATE,
HCLGE_SHAPER_LVL_PORT,
&ir_b, &ir_u, &ir_s);
if (ret)
return ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PORT_SHAPPING, false);
shap_cfg_cmd = (struct hclge_port_shapping_cmd *)desc.data;
hclge_tm_set_field(shapping_para, IR_B, ir_b);
hclge_tm_set_field(shapping_para, IR_U, ir_u);
hclge_tm_set_field(shapping_para, IR_S, ir_s);
hclge_tm_set_field(shapping_para, BS_B, HCLGE_SHAPER_BS_U_DEF);
hclge_tm_set_field(shapping_para, BS_S, HCLGE_SHAPER_BS_S_DEF);
shap_cfg_cmd->port_shapping_para = cpu_to_le32(shapping_para);
return hclge_cmd_send(&hdev->hw, &desc, 1);
}
static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev, static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev,
enum hclge_shap_bucket bucket, u8 pri_id, enum hclge_shap_bucket bucket, u8 pri_id,
u8 ir_b, u8 ir_u, u8 ir_s, u8 ir_b, u8 ir_u, u8 ir_s,
...@@ -346,13 +388,13 @@ static int hclge_tm_pri_schd_mode_cfg(struct hclge_dev *hdev, u8 pri_id) ...@@ -346,13 +388,13 @@ static int hclge_tm_pri_schd_mode_cfg(struct hclge_dev *hdev, u8 pri_id)
return hclge_cmd_send(&hdev->hw, &desc, 1); return hclge_cmd_send(&hdev->hw, &desc, 1);
} }
static int hclge_tm_qs_schd_mode_cfg(struct hclge_dev *hdev, u16 qs_id) static int hclge_tm_qs_schd_mode_cfg(struct hclge_dev *hdev, u16 qs_id, u8 mode)
{ {
struct hclge_desc desc; struct hclge_desc desc;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_SCH_MODE_CFG, false); hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_SCH_MODE_CFG, false);
if (hdev->tm_info.tc_info[qs_id].tc_sch_mode == HCLGE_SCH_MODE_DWRR) if (mode == HCLGE_SCH_MODE_DWRR)
desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK); desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK);
else else
desc.data[1] = 0; desc.data[1] = 0;
...@@ -444,6 +486,10 @@ static void hclge_tm_tc_info_init(struct hclge_dev *hdev) ...@@ -444,6 +486,10 @@ static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
hdev->tm_info.prio_tc[i] = hdev->tm_info.prio_tc[i] =
(i >= hdev->tm_info.num_tc) ? 0 : i; (i >= hdev->tm_info.num_tc) ? 0 : i;
/* DCB is enabled if we have more than 1 TC */
if (hdev->tm_info.num_tc > 1)
hdev->flag |= HCLGE_FLAG_DCB_ENABLE;
else
hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
} }
...@@ -470,6 +516,24 @@ static void hclge_tm_pg_info_init(struct hclge_dev *hdev) ...@@ -470,6 +516,24 @@ static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
} }
} }
static void hclge_pfc_info_init(struct hclge_dev *hdev)
{
if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) {
if (hdev->fc_mode_last_time == HCLGE_FC_PFC)
dev_warn(&hdev->pdev->dev,
"DCB is disable, but last mode is FC_PFC\n");
hdev->tm_info.fc_mode = hdev->fc_mode_last_time;
} else if (hdev->tm_info.fc_mode != HCLGE_FC_PFC) {
/* fc_mode_last_time record the last fc_mode when
* DCB is enabled, so that fc_mode can be set to
* the correct value when DCB is disabled.
*/
hdev->fc_mode_last_time = hdev->tm_info.fc_mode;
hdev->tm_info.fc_mode = HCLGE_FC_PFC;
}
}
static int hclge_tm_schd_info_init(struct hclge_dev *hdev) static int hclge_tm_schd_info_init(struct hclge_dev *hdev)
{ {
if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) && if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) &&
...@@ -482,8 +546,7 @@ static int hclge_tm_schd_info_init(struct hclge_dev *hdev) ...@@ -482,8 +546,7 @@ static int hclge_tm_schd_info_init(struct hclge_dev *hdev)
hclge_tm_vport_info_update(hdev); hclge_tm_vport_info_update(hdev);
hdev->tm_info.fc_mode = HCLGE_FC_NONE; hclge_pfc_info_init(hdev);
hdev->fc_mode_last_time = hdev->tm_info.fc_mode;
return 0; return 0;
} }
...@@ -596,17 +659,18 @@ static int hclge_tm_pri_q_qs_cfg(struct hclge_dev *hdev) ...@@ -596,17 +659,18 @@ static int hclge_tm_pri_q_qs_cfg(struct hclge_dev *hdev)
{ {
struct hclge_vport *vport = hdev->vport; struct hclge_vport *vport = hdev->vport;
int ret; int ret;
u32 i; u32 i, k;
if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
/* Cfg qs -> pri mapping, one by one mapping */ /* Cfg qs -> pri mapping, one by one mapping */
for (k = 0; k < hdev->num_alloc_vport; k++)
for (i = 0; i < hdev->tm_info.num_tc; i++) { for (i = 0; i < hdev->tm_info.num_tc; i++) {
ret = hclge_tm_qs_to_pri_map_cfg(hdev, i, i); ret = hclge_tm_qs_to_pri_map_cfg(
hdev, vport[k].qs_offset + i, i);
if (ret) if (ret)
return ret; return ret;
} }
} else if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) { } else if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) {
int k;
/* Cfg qs -> pri mapping, qs = tc, pri = vf, 8 qs -> 1 pri */ /* Cfg qs -> pri mapping, qs = tc, pri = vf, 8 qs -> 1 pri */
for (k = 0; k < hdev->num_alloc_vport; k++) for (k = 0; k < hdev->num_alloc_vport; k++)
for (i = 0; i < HNAE3_MAX_TC; i++) { for (i = 0; i < HNAE3_MAX_TC; i++) {
...@@ -755,10 +819,11 @@ static int hclge_tm_pri_shaper_cfg(struct hclge_dev *hdev) ...@@ -755,10 +819,11 @@ static int hclge_tm_pri_shaper_cfg(struct hclge_dev *hdev)
static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev) static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev)
{ {
struct hclge_vport *vport = hdev->vport;
struct hclge_pg_info *pg_info; struct hclge_pg_info *pg_info;
u8 dwrr; u8 dwrr;
int ret; int ret;
u32 i; u32 i, k;
for (i = 0; i < hdev->tm_info.num_tc; i++) { for (i = 0; i < hdev->tm_info.num_tc; i++) {
pg_info = pg_info =
...@@ -769,10 +834,14 @@ static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev) ...@@ -769,10 +834,14 @@ static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev)
if (ret) if (ret)
return ret; return ret;
ret = hclge_tm_qs_weight_cfg(hdev, i, dwrr); for (k = 0; k < hdev->num_alloc_vport; k++) {
ret = hclge_tm_qs_weight_cfg(
hdev, vport[k].qs_offset + i,
vport[k].dwrr);
if (ret) if (ret)
return ret; return ret;
} }
}
return 0; return 0;
} }
...@@ -835,10 +904,14 @@ static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev) ...@@ -835,10 +904,14 @@ static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev)
return 0; return 0;
} }
static int hclge_tm_map_cfg(struct hclge_dev *hdev) int hclge_tm_map_cfg(struct hclge_dev *hdev)
{ {
int ret; int ret;
ret = hclge_up_to_tc_map(hdev);
if (ret)
return ret;
ret = hclge_tm_pg_to_pri_map(hdev); ret = hclge_tm_pg_to_pri_map(hdev);
if (ret) if (ret)
return ret; return ret;
...@@ -850,6 +923,10 @@ static int hclge_tm_shaper_cfg(struct hclge_dev *hdev) ...@@ -850,6 +923,10 @@ static int hclge_tm_shaper_cfg(struct hclge_dev *hdev)
{ {
int ret; int ret;
ret = hclge_tm_port_shaper_cfg(hdev);
if (ret)
return ret;
ret = hclge_tm_pg_shaper_cfg(hdev); ret = hclge_tm_pg_shaper_cfg(hdev);
if (ret) if (ret)
return ret; return ret;
...@@ -898,7 +975,10 @@ static int hclge_tm_schd_mode_vnet_base_cfg(struct hclge_vport *vport) ...@@ -898,7 +975,10 @@ static int hclge_tm_schd_mode_vnet_base_cfg(struct hclge_vport *vport)
return ret; return ret;
for (i = 0; i < kinfo->num_tc; i++) { for (i = 0; i < kinfo->num_tc; i++) {
ret = hclge_tm_qs_schd_mode_cfg(hdev, vport->qs_offset + i); u8 sch_mode = hdev->tm_info.tc_info[i].tc_sch_mode;
ret = hclge_tm_qs_schd_mode_cfg(hdev, vport->qs_offset + i,
sch_mode);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -910,7 +990,7 @@ static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev) ...@@ -910,7 +990,7 @@ static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev)
{ {
struct hclge_vport *vport = hdev->vport; struct hclge_vport *vport = hdev->vport;
int ret; int ret;
u8 i; u8 i, k;
if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
for (i = 0; i < hdev->tm_info.num_tc; i++) { for (i = 0; i < hdev->tm_info.num_tc; i++) {
...@@ -918,10 +998,14 @@ static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev) ...@@ -918,10 +998,14 @@ static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev)
if (ret) if (ret)
return ret; return ret;
ret = hclge_tm_qs_schd_mode_cfg(hdev, i); for (k = 0; k < hdev->num_alloc_vport; k++) {
ret = hclge_tm_qs_schd_mode_cfg(
hdev, vport[k].qs_offset + i,
HCLGE_SCH_MODE_DWRR);
if (ret) if (ret)
return ret; return ret;
} }
}
} else { } else {
for (i = 0; i < hdev->num_alloc_vport; i++) { for (i = 0; i < hdev->num_alloc_vport; i++) {
ret = hclge_tm_schd_mode_vnet_base_cfg(vport); ret = hclge_tm_schd_mode_vnet_base_cfg(vport);
...@@ -935,7 +1019,7 @@ static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev) ...@@ -935,7 +1019,7 @@ static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev)
return 0; return 0;
} }
static int hclge_tm_schd_mode_hw(struct hclge_dev *hdev) int hclge_tm_schd_mode_hw(struct hclge_dev *hdev)
{ {
int ret; int ret;
...@@ -969,27 +1053,109 @@ static int hclge_tm_schd_setup_hw(struct hclge_dev *hdev) ...@@ -969,27 +1053,109 @@ static int hclge_tm_schd_setup_hw(struct hclge_dev *hdev)
return hclge_tm_schd_mode_hw(hdev); return hclge_tm_schd_mode_hw(hdev);
} }
static int hclge_pfc_setup_hw(struct hclge_dev *hdev)
{
u8 enable_bitmap = 0;
if (hdev->tm_info.fc_mode == HCLGE_FC_PFC)
enable_bitmap = HCLGE_TX_MAC_PAUSE_EN_MSK |
HCLGE_RX_MAC_PAUSE_EN_MSK;
return hclge_pfc_pause_en_cfg(hdev, enable_bitmap,
hdev->tm_info.hw_pfc_map);
}
static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
{
bool tx_en, rx_en;
switch (hdev->tm_info.fc_mode) {
case HCLGE_FC_NONE:
tx_en = false;
rx_en = false;
break;
case HCLGE_FC_RX_PAUSE:
tx_en = false;
rx_en = true;
break;
case HCLGE_FC_TX_PAUSE:
tx_en = true;
rx_en = false;
break;
case HCLGE_FC_FULL:
tx_en = true;
rx_en = true;
break;
default:
tx_en = true;
rx_en = true;
}
return hclge_mac_pause_en_cfg(hdev, tx_en, rx_en);
}
int hclge_pause_setup_hw(struct hclge_dev *hdev) int hclge_pause_setup_hw(struct hclge_dev *hdev)
{ {
bool en = hdev->tm_info.fc_mode != HCLGE_FC_PFC;
int ret; int ret;
u8 i; u8 i;
ret = hclge_mac_pause_en_cfg(hdev, en, en); if (hdev->tm_info.fc_mode != HCLGE_FC_PFC)
if (ret) return hclge_mac_pause_setup_hw(hdev);
return ret;
/* Only DCB-supported dev supports qset back pressure setting */ /* Only DCB-supported dev supports qset back pressure and pfc cmd */
if (!hnae3_dev_dcb_supported(hdev)) if (!hnae3_dev_dcb_supported(hdev))
return 0; return 0;
/* When MAC is GE Mode, hdev does not support pfc setting */
ret = hclge_pfc_setup_hw(hdev);
if (ret)
dev_warn(&hdev->pdev->dev, "set pfc pause failed:%d\n", ret);
for (i = 0; i < hdev->tm_info.num_tc; i++) { for (i = 0; i < hdev->tm_info.num_tc; i++) {
ret = hclge_tm_qs_bp_cfg(hdev, i); ret = hclge_tm_qs_bp_cfg(hdev, i);
if (ret) if (ret)
return ret; return ret;
} }
return hclge_up_to_tc_map(hdev); return 0;
}
int hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc)
{
struct hclge_vport *vport = hdev->vport;
struct hnae3_knic_private_info *kinfo;
u32 i, k;
for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {
if (prio_tc[i] >= hdev->tm_info.num_tc)
return -EINVAL;
hdev->tm_info.prio_tc[i] = prio_tc[i];
for (k = 0; k < hdev->num_alloc_vport; k++) {
kinfo = &vport[k].nic.kinfo;
kinfo->prio_tc[i] = prio_tc[i];
}
}
return 0;
}
void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc)
{
u8 i, bit_map = 0;
hdev->tm_info.num_tc = num_tc;
for (i = 0; i < hdev->tm_info.num_tc; i++)
bit_map |= BIT(i);
if (!bit_map) {
bit_map = 1;
hdev->tm_info.num_tc = 1;
}
hdev->hw_tc_map = bit_map;
hclge_tm_schd_info_init(hdev);
} }
int hclge_tm_init_hw(struct hclge_dev *hdev) int hclge_tm_init_hw(struct hclge_dev *hdev)
...@@ -1013,8 +1179,13 @@ int hclge_tm_init_hw(struct hclge_dev *hdev) ...@@ -1013,8 +1179,13 @@ int hclge_tm_init_hw(struct hclge_dev *hdev)
int hclge_tm_schd_init(struct hclge_dev *hdev) int hclge_tm_schd_init(struct hclge_dev *hdev)
{ {
int ret = hclge_tm_schd_info_init(hdev); int ret;
/* fc_mode is HCLGE_FC_FULL on reset */
hdev->tm_info.fc_mode = HCLGE_FC_FULL;
hdev->fc_mode_last_time = hdev->tm_info.fc_mode;
ret = hclge_tm_schd_info_init(hdev);
if (ret) if (ret)
return ret; return ret;
......
...@@ -94,6 +94,15 @@ struct hclge_bp_to_qs_map_cmd { ...@@ -94,6 +94,15 @@ struct hclge_bp_to_qs_map_cmd {
u32 rsvd1; u32 rsvd1;
}; };
struct hclge_pfc_en_cmd {
u8 tx_rx_en_bitmap;
u8 pri_en_bitmap;
};
struct hclge_port_shapping_cmd {
__le32 port_shapping_para;
};
#define hclge_tm_set_field(dest, string, val) \ #define hclge_tm_set_field(dest, string, val) \
hnae_set_field((dest), (HCLGE_TM_SHAP_##string##_MSK), \ hnae_set_field((dest), (HCLGE_TM_SHAP_##string##_MSK), \
(HCLGE_TM_SHAP_##string##_LSH), val) (HCLGE_TM_SHAP_##string##_LSH), val)
...@@ -103,4 +112,10 @@ struct hclge_bp_to_qs_map_cmd { ...@@ -103,4 +112,10 @@ struct hclge_bp_to_qs_map_cmd {
int hclge_tm_schd_init(struct hclge_dev *hdev); int hclge_tm_schd_init(struct hclge_dev *hdev);
int hclge_pause_setup_hw(struct hclge_dev *hdev); int hclge_pause_setup_hw(struct hclge_dev *hdev);
int hclge_tm_schd_mode_hw(struct hclge_dev *hdev);
int hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc);
void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc);
int hclge_tm_dwrr_cfg(struct hclge_dev *hdev);
int hclge_tm_map_cfg(struct hclge_dev *hdev);
int hclge_tm_init_hw(struct hclge_dev *hdev);
#endif #endif
/*
* Copyright (c) 2016-2017 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "hnae3.h"
#include "hns3_enet.h"
static
int hns3_dcbnl_ieee_getets(struct net_device *ndev, struct ieee_ets *ets)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
if (h->kinfo.dcb_ops->ieee_getets)
return h->kinfo.dcb_ops->ieee_getets(h, ets);
return -EOPNOTSUPP;
}
static
int hns3_dcbnl_ieee_setets(struct net_device *ndev, struct ieee_ets *ets)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
if (h->kinfo.dcb_ops->ieee_setets)
return h->kinfo.dcb_ops->ieee_setets(h, ets);
return -EOPNOTSUPP;
}
static
int hns3_dcbnl_ieee_getpfc(struct net_device *ndev, struct ieee_pfc *pfc)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
if (h->kinfo.dcb_ops->ieee_getpfc)
return h->kinfo.dcb_ops->ieee_getpfc(h, pfc);
return -EOPNOTSUPP;
}
static
int hns3_dcbnl_ieee_setpfc(struct net_device *ndev, struct ieee_pfc *pfc)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
if (h->kinfo.dcb_ops->ieee_setpfc)
return h->kinfo.dcb_ops->ieee_setpfc(h, pfc);
return -EOPNOTSUPP;
}
/* DCBX configuration */
static u8 hns3_dcbnl_getdcbx(struct net_device *ndev)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
if (h->kinfo.dcb_ops->getdcbx)
return h->kinfo.dcb_ops->getdcbx(h);
return 0;
}
/* return 0 if successful, otherwise fail */
static u8 hns3_dcbnl_setdcbx(struct net_device *ndev, u8 mode)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
if (h->kinfo.dcb_ops->setdcbx)
return h->kinfo.dcb_ops->setdcbx(h, mode);
return 1;
}
static const struct dcbnl_rtnl_ops hns3_dcbnl_ops = {
.ieee_getets = hns3_dcbnl_ieee_getets,
.ieee_setets = hns3_dcbnl_ieee_setets,
.ieee_getpfc = hns3_dcbnl_ieee_getpfc,
.ieee_setpfc = hns3_dcbnl_ieee_setpfc,
.getdcbx = hns3_dcbnl_getdcbx,
.setdcbx = hns3_dcbnl_setdcbx,
};
/* hclge_dcbnl_setup - DCBNL setup
* @handle: the corresponding vport handle
* Set up DCBNL
*/
void hns3_dcbnl_setup(struct hnae3_handle *handle)
{
struct net_device *dev = handle->kinfo.netdev;
if (!handle->kinfo.dcb_ops)
return;
dev->dcbnl_ops = &hns3_dcbnl_ops;
}
...@@ -196,6 +196,32 @@ static void hns3_vector_gl_rl_init(struct hns3_enet_tqp_vector *tqp_vector) ...@@ -196,6 +196,32 @@ static void hns3_vector_gl_rl_init(struct hns3_enet_tqp_vector *tqp_vector)
tqp_vector->tx_group.flow_level = HNS3_FLOW_LOW; tqp_vector->tx_group.flow_level = HNS3_FLOW_LOW;
} }
static int hns3_nic_set_real_num_queue(struct net_device *netdev)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
struct hnae3_knic_private_info *kinfo = &h->kinfo;
unsigned int queue_size = kinfo->rss_size * kinfo->num_tc;
int ret;
ret = netif_set_real_num_tx_queues(netdev, queue_size);
if (ret) {
netdev_err(netdev,
"netif_set_real_num_tx_queues fail, ret=%d!\n",
ret);
return ret;
}
ret = netif_set_real_num_rx_queues(netdev, queue_size);
if (ret) {
netdev_err(netdev,
"netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
return ret;
}
return 0;
}
static int hns3_nic_net_up(struct net_device *netdev) static int hns3_nic_net_up(struct net_device *netdev)
{ {
struct hns3_nic_priv *priv = netdev_priv(netdev); struct hns3_nic_priv *priv = netdev_priv(netdev);
...@@ -232,26 +258,13 @@ static int hns3_nic_net_up(struct net_device *netdev) ...@@ -232,26 +258,13 @@ static int hns3_nic_net_up(struct net_device *netdev)
static int hns3_nic_net_open(struct net_device *netdev) static int hns3_nic_net_open(struct net_device *netdev)
{ {
struct hns3_nic_priv *priv = netdev_priv(netdev);
struct hnae3_handle *h = priv->ae_handle;
int ret; int ret;
netif_carrier_off(netdev); netif_carrier_off(netdev);
ret = netif_set_real_num_tx_queues(netdev, h->kinfo.num_tqps); ret = hns3_nic_set_real_num_queue(netdev);
if (ret) { if (ret)
netdev_err(netdev,
"netif_set_real_num_tx_queues fail, ret=%d!\n",
ret);
return ret;
}
ret = netif_set_real_num_rx_queues(netdev, h->kinfo.num_tqps);
if (ret) {
netdev_err(netdev,
"netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
return ret; return ret;
}
ret = hns3_nic_net_up(netdev); ret = hns3_nic_net_up(netdev);
if (ret) { if (ret) {
...@@ -2790,6 +2803,8 @@ static int hns3_client_init(struct hnae3_handle *handle) ...@@ -2790,6 +2803,8 @@ static int hns3_client_init(struct hnae3_handle *handle)
goto out_reg_netdev_fail; goto out_reg_netdev_fail;
} }
hns3_dcbnl_setup(handle);
/* MTU range: (ETH_MIN_MTU(kernel default) - 9706) */ /* MTU range: (ETH_MIN_MTU(kernel default) - 9706) */
netdev->max_mtu = HNS3_MAX_MTU - (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); netdev->max_mtu = HNS3_MAX_MTU - (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
...@@ -2846,10 +2861,69 @@ static void hns3_link_status_change(struct hnae3_handle *handle, bool linkup) ...@@ -2846,10 +2861,69 @@ static void hns3_link_status_change(struct hnae3_handle *handle, bool linkup)
} }
} }
static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc)
{
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
struct net_device *ndev = kinfo->netdev;
bool if_running = netif_running(ndev);
int ret;
u8 i;
if (tc > HNAE3_MAX_TC)
return -EINVAL;
if (!ndev)
return -ENODEV;
ret = netdev_set_num_tc(ndev, tc);
if (ret)
return ret;
if (if_running) {
(void)hns3_nic_net_stop(ndev);
msleep(100);
}
ret = (kinfo->dcb_ops && kinfo->dcb_ops->map_update) ?
kinfo->dcb_ops->map_update(handle) : -EOPNOTSUPP;
if (ret)
goto err_out;
if (tc <= 1) {
netdev_reset_tc(ndev);
goto out;
}
for (i = 0; i < HNAE3_MAX_TC; i++) {
struct hnae3_tc_info *tc_info = &kinfo->tc_info[i];
if (tc_info->enable)
netdev_set_tc_queue(ndev,
tc_info->tc,
tc_info->tqp_count,
tc_info->tqp_offset);
}
for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {
netdev_set_prio_tc_map(ndev, i,
kinfo->prio_tc[i]);
}
out:
ret = hns3_nic_set_real_num_queue(ndev);
err_out:
if (if_running)
(void)hns3_nic_net_open(ndev);
return ret;
}
const struct hnae3_client_ops client_ops = { const struct hnae3_client_ops client_ops = {
.init_instance = hns3_client_init, .init_instance = hns3_client_init,
.uninit_instance = hns3_client_uninit, .uninit_instance = hns3_client_uninit,
.link_status_change = hns3_link_status_change, .link_status_change = hns3_link_status_change,
.setup_tc = hns3_client_setup_tc,
}; };
/* hns3_init_module - Driver registration routine /* hns3_init_module - Driver registration routine
......
...@@ -590,4 +590,11 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value) ...@@ -590,4 +590,11 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
void hns3_ethtool_set_ops(struct net_device *netdev); void hns3_ethtool_set_ops(struct net_device *netdev);
int hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget); int hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget);
#ifdef CONFIG_HNS3_DCB
void hns3_dcbnl_setup(struct hnae3_handle *handle);
#else
static inline void hns3_dcbnl_setup(struct hnae3_handle *handle) {}
#endif
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment