Commit 59d43876 authored by David S. Miller's avatar David S. Miller

Merge branch 'hnx3-rxnfc'

Lipeng says:

====================
Support set_ringparam and {set|get}_rxnfc ethtool commands

1, Patch [1/5,2/5] add support for ethtool ops set_ringparam
   (ethtool -G) and fix related bug.
2, Patch [3/5,4/5, 5/5] add support for ethtool ops
   set_rxnfc/get_rxnfc (-n/-N) and fix related bug.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 652faa98 abf11d04
...@@ -339,6 +339,10 @@ struct hnae3_ae_ops { ...@@ -339,6 +339,10 @@ struct hnae3_ae_ops {
u8 *hfunc); u8 *hfunc);
int (*set_rss)(struct hnae3_handle *handle, const u32 *indir, int (*set_rss)(struct hnae3_handle *handle, const u32 *indir,
const u8 *key, const u8 hfunc); const u8 *key, const u8 hfunc);
int (*set_rss_tuple)(struct hnae3_handle *handle,
struct ethtool_rxnfc *cmd);
int (*get_rss_tuple)(struct hnae3_handle *handle,
struct ethtool_rxnfc *cmd);
int (*get_tc_size)(struct hnae3_handle *handle); int (*get_tc_size)(struct hnae3_handle *handle);
......
...@@ -85,6 +85,15 @@ static int hclge_init_cmd_queue(struct hclge_dev *hdev, int ring_type) ...@@ -85,6 +85,15 @@ static int hclge_init_cmd_queue(struct hclge_dev *hdev, int ring_type)
return 0; return 0;
} }
void hclge_cmd_reuse_desc(struct hclge_desc *desc, bool is_read)
{
desc->flag = cpu_to_le16(HCLGE_CMD_FLAG_NO_INTR | HCLGE_CMD_FLAG_IN);
if (is_read)
desc->flag |= cpu_to_le16(HCLGE_CMD_FLAG_WR);
else
desc->flag &= cpu_to_le16(~HCLGE_CMD_FLAG_WR);
}
void hclge_cmd_setup_basic_desc(struct hclge_desc *desc, void hclge_cmd_setup_basic_desc(struct hclge_desc *desc,
enum hclge_opcode_type opcode, bool is_read) enum hclge_opcode_type opcode, bool is_read)
{ {
......
...@@ -739,6 +739,7 @@ struct hclge_hw; ...@@ -739,6 +739,7 @@ struct hclge_hw;
int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num); int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num);
void hclge_cmd_setup_basic_desc(struct hclge_desc *desc, void hclge_cmd_setup_basic_desc(struct hclge_desc *desc,
enum hclge_opcode_type opcode, bool is_read); enum hclge_opcode_type opcode, bool is_read);
void hclge_cmd_reuse_desc(struct hclge_desc *desc, bool is_read);
int hclge_cmd_set_promisc_mode(struct hclge_dev *hdev, int hclge_cmd_set_promisc_mode(struct hclge_dev *hdev,
struct hclge_promisc_param *param); struct hclge_promisc_param *param);
......
...@@ -2595,8 +2595,6 @@ static int hclge_set_rss_tc_mode(struct hclge_dev *hdev, u16 *tc_valid, ...@@ -2595,8 +2595,6 @@ static int hclge_set_rss_tc_mode(struct hclge_dev *hdev, u16 *tc_valid,
static int hclge_set_rss_input_tuple(struct hclge_dev *hdev) static int hclge_set_rss_input_tuple(struct hclge_dev *hdev)
{ {
#define HCLGE_RSS_INPUT_TUPLE_OTHER 0xf
#define HCLGE_RSS_INPUT_TUPLE_SCTP 0x1f
struct hclge_rss_input_tuple_cmd *req; struct hclge_rss_input_tuple_cmd *req;
struct hclge_desc desc; struct hclge_desc desc;
int ret; int ret;
...@@ -2677,6 +2675,161 @@ static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir, ...@@ -2677,6 +2675,161 @@ static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir,
return ret; return ret;
} }
static u8 hclge_get_rss_hash_bits(struct ethtool_rxnfc *nfc)
{
u8 hash_sets = nfc->data & RXH_L4_B_0_1 ? HCLGE_S_PORT_BIT : 0;
if (nfc->data & RXH_L4_B_2_3)
hash_sets |= HCLGE_D_PORT_BIT;
else
hash_sets &= ~HCLGE_D_PORT_BIT;
if (nfc->data & RXH_IP_SRC)
hash_sets |= HCLGE_S_IP_BIT;
else
hash_sets &= ~HCLGE_S_IP_BIT;
if (nfc->data & RXH_IP_DST)
hash_sets |= HCLGE_D_IP_BIT;
else
hash_sets &= ~HCLGE_D_IP_BIT;
if (nfc->flow_type == SCTP_V4_FLOW || nfc->flow_type == SCTP_V6_FLOW)
hash_sets |= HCLGE_V_TAG_BIT;
return hash_sets;
}
static int hclge_set_rss_tuple(struct hnae3_handle *handle,
struct ethtool_rxnfc *nfc)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_rss_input_tuple_cmd *req;
struct hclge_desc desc;
u8 tuple_sets;
int ret;
if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
RXH_L4_B_0_1 | RXH_L4_B_2_3))
return -EINVAL;
req = (struct hclge_rss_input_tuple_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RSS_INPUT_TUPLE, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
"Read rss tuple fail, status = %d\n", ret);
return ret;
}
hclge_cmd_reuse_desc(&desc, false);
tuple_sets = hclge_get_rss_hash_bits(nfc);
switch (nfc->flow_type) {
case TCP_V4_FLOW:
req->ipv4_tcp_en = tuple_sets;
break;
case TCP_V6_FLOW:
req->ipv6_tcp_en = tuple_sets;
break;
case UDP_V4_FLOW:
req->ipv4_udp_en = tuple_sets;
break;
case UDP_V6_FLOW:
req->ipv6_udp_en = tuple_sets;
break;
case SCTP_V4_FLOW:
req->ipv4_sctp_en = tuple_sets;
break;
case SCTP_V6_FLOW:
if ((nfc->data & RXH_L4_B_0_1) ||
(nfc->data & RXH_L4_B_2_3))
return -EINVAL;
req->ipv6_sctp_en = tuple_sets;
break;
case IPV4_FLOW:
req->ipv4_fragment_en = HCLGE_RSS_INPUT_TUPLE_OTHER;
break;
case IPV6_FLOW:
req->ipv6_fragment_en = HCLGE_RSS_INPUT_TUPLE_OTHER;
break;
default:
return -EINVAL;
}
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret)
dev_err(&hdev->pdev->dev,
"Set rss tuple fail, status = %d\n", ret);
return ret;
}
static int hclge_get_rss_tuple(struct hnae3_handle *handle,
struct ethtool_rxnfc *nfc)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_rss_input_tuple_cmd *req;
struct hclge_desc desc;
u8 tuple_sets;
int ret;
nfc->data = 0;
req = (struct hclge_rss_input_tuple_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RSS_INPUT_TUPLE, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
"Read rss tuple fail, status = %d\n", ret);
return ret;
}
switch (nfc->flow_type) {
case TCP_V4_FLOW:
tuple_sets = req->ipv4_tcp_en;
break;
case UDP_V4_FLOW:
tuple_sets = req->ipv4_udp_en;
break;
case TCP_V6_FLOW:
tuple_sets = req->ipv6_tcp_en;
break;
case UDP_V6_FLOW:
tuple_sets = req->ipv6_udp_en;
break;
case SCTP_V4_FLOW:
tuple_sets = req->ipv4_sctp_en;
break;
case SCTP_V6_FLOW:
tuple_sets = req->ipv6_sctp_en;
break;
case IPV4_FLOW:
case IPV6_FLOW:
tuple_sets = HCLGE_S_IP_BIT | HCLGE_D_IP_BIT;
break;
default:
return -EINVAL;
}
if (!tuple_sets)
return 0;
if (tuple_sets & HCLGE_D_PORT_BIT)
nfc->data |= RXH_L4_B_2_3;
if (tuple_sets & HCLGE_S_PORT_BIT)
nfc->data |= RXH_L4_B_0_1;
if (tuple_sets & HCLGE_D_IP_BIT)
nfc->data |= RXH_IP_DST;
if (tuple_sets & HCLGE_S_IP_BIT)
nfc->data |= RXH_IP_SRC;
return 0;
}
static int hclge_get_tc_size(struct hnae3_handle *handle) static int hclge_get_tc_size(struct hnae3_handle *handle)
{ {
struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_vport *vport = hclge_get_vport(handle);
...@@ -4344,6 +4497,8 @@ static const struct hnae3_ae_ops hclge_ops = { ...@@ -4344,6 +4497,8 @@ static const struct hnae3_ae_ops hclge_ops = {
.get_rss_indir_size = hclge_get_rss_indir_size, .get_rss_indir_size = hclge_get_rss_indir_size,
.get_rss = hclge_get_rss, .get_rss = hclge_get_rss,
.set_rss = hclge_set_rss, .set_rss = hclge_set_rss,
.set_rss_tuple = hclge_set_rss_tuple,
.get_rss_tuple = hclge_get_rss_tuple,
.get_tc_size = hclge_get_tc_size, .get_tc_size = hclge_get_tc_size,
.get_mac_addr = hclge_get_mac_addr, .get_mac_addr = hclge_get_mac_addr,
.set_mac_addr = hclge_set_mac_addr, .set_mac_addr = hclge_set_mac_addr,
......
...@@ -41,6 +41,14 @@ ...@@ -41,6 +41,14 @@
#define HCLGE_RSS_CFG_TBL_NUM \ #define HCLGE_RSS_CFG_TBL_NUM \
(HCLGE_RSS_IND_TBL_SIZE / HCLGE_RSS_CFG_TBL_SIZE) (HCLGE_RSS_IND_TBL_SIZE / HCLGE_RSS_CFG_TBL_SIZE)
#define HCLGE_RSS_INPUT_TUPLE_OTHER GENMASK(3, 0)
#define HCLGE_RSS_INPUT_TUPLE_SCTP GENMASK(4, 0)
#define HCLGE_D_PORT_BIT BIT(0)
#define HCLGE_S_PORT_BIT BIT(1)
#define HCLGE_D_IP_BIT BIT(2)
#define HCLGE_S_IP_BIT BIT(3)
#define HCLGE_V_TAG_BIT BIT(4)
#define HCLGE_RSS_TC_SIZE_0 1 #define HCLGE_RSS_TC_SIZE_0 1
#define HCLGE_RSS_TC_SIZE_1 2 #define HCLGE_RSS_TC_SIZE_1 2
#define HCLGE_RSS_TC_SIZE_2 4 #define HCLGE_RSS_TC_SIZE_2 4
......
...@@ -2637,7 +2637,7 @@ static void hns3_init_ring_hw(struct hns3_enet_ring *ring) ...@@ -2637,7 +2637,7 @@ static void hns3_init_ring_hw(struct hns3_enet_ring *ring)
} }
} }
static int hns3_init_all_ring(struct hns3_nic_priv *priv) int hns3_init_all_ring(struct hns3_nic_priv *priv)
{ {
struct hnae3_handle *h = priv->ae_handle; struct hnae3_handle *h = priv->ae_handle;
int ring_num = h->kinfo.num_tqps * 2; int ring_num = h->kinfo.num_tqps * 2;
...@@ -2661,12 +2661,12 @@ static int hns3_init_all_ring(struct hns3_nic_priv *priv) ...@@ -2661,12 +2661,12 @@ static int hns3_init_all_ring(struct hns3_nic_priv *priv)
out_when_alloc_ring_memory: out_when_alloc_ring_memory:
for (j = i - 1; j >= 0; j--) for (j = i - 1; j >= 0; j--)
hns3_fini_ring(priv->ring_data[i].ring); hns3_fini_ring(priv->ring_data[j].ring);
return -ENOMEM; return -ENOMEM;
} }
static int hns3_uninit_all_ring(struct hns3_nic_priv *priv) int hns3_uninit_all_ring(struct hns3_nic_priv *priv)
{ {
struct hnae3_handle *h = priv->ae_handle; struct hnae3_handle *h = priv->ae_handle;
int i; int i;
......
...@@ -76,6 +76,8 @@ enum hns3_nic_state { ...@@ -76,6 +76,8 @@ enum hns3_nic_state {
#define HNS3_RING_NAME_LEN 16 #define HNS3_RING_NAME_LEN 16
#define HNS3_BUFFER_SIZE_2048 2048 #define HNS3_BUFFER_SIZE_2048 2048
#define HNS3_RING_MAX_PENDING 32768 #define HNS3_RING_MAX_PENDING 32768
#define HNS3_RING_MIN_PENDING 8
#define HNS3_RING_BD_MULTIPLE 8
#define HNS3_MAX_MTU 9728 #define HNS3_MAX_MTU 9728
#define HNS3_BD_SIZE_512_TYPE 0 #define HNS3_BD_SIZE_512_TYPE 0
...@@ -593,6 +595,8 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value) ...@@ -593,6 +595,8 @@ 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);
int hns3_init_all_ring(struct hns3_nic_priv *priv);
int hns3_uninit_all_ring(struct hns3_nic_priv *priv);
#ifdef CONFIG_HNS3_DCB #ifdef CONFIG_HNS3_DCB
void hns3_dcbnl_setup(struct hnae3_handle *handle); void hns3_dcbnl_setup(struct hnae3_handle *handle);
......
...@@ -450,8 +450,10 @@ static int hns3_get_rxnfc(struct net_device *netdev, ...@@ -450,8 +450,10 @@ static int hns3_get_rxnfc(struct net_device *netdev,
switch (cmd->cmd) { switch (cmd->cmd) {
case ETHTOOL_GRXRINGS: case ETHTOOL_GRXRINGS:
cmd->data = h->ae_algo->ops->get_tc_size(h); cmd->data = h->kinfo.num_tc * h->kinfo.rss_size;
break; break;
case ETHTOOL_GRXFH:
return h->ae_algo->ops->get_rss_tuple(h, cmd);
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -459,15 +461,106 @@ static int hns3_get_rxnfc(struct net_device *netdev, ...@@ -459,15 +461,106 @@ static int hns3_get_rxnfc(struct net_device *netdev,
return 0; return 0;
} }
int hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv, u32 new_desc_num)
{
struct hnae3_handle *h = priv->ae_handle;
int i;
h->kinfo.num_desc = new_desc_num;
for (i = 0; i < h->kinfo.num_tqps * 2; i++)
priv->ring_data[i].ring->desc_num = new_desc_num;
return hns3_init_all_ring(priv);
}
int hns3_set_ringparam(struct net_device *ndev, struct ethtool_ringparam *param)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
bool if_running = netif_running(ndev);
u32 old_desc_num, new_desc_num;
int ret;
if (param->rx_mini_pending || param->rx_jumbo_pending)
return -EINVAL;
if (param->tx_pending != param->rx_pending) {
netdev_err(ndev,
"Descriptors of tx and rx must be equal");
return -EINVAL;
}
if (param->tx_pending > HNS3_RING_MAX_PENDING ||
param->tx_pending < HNS3_RING_MIN_PENDING) {
netdev_err(ndev,
"Descriptors requested (Tx/Rx: %d) out of range [%d-%d]\n",
param->tx_pending, HNS3_RING_MIN_PENDING,
HNS3_RING_MAX_PENDING);
return -EINVAL;
}
new_desc_num = param->tx_pending;
/* Hardware requires that its descriptors must be multiple of eight */
new_desc_num = ALIGN(new_desc_num, HNS3_RING_BD_MULTIPLE);
old_desc_num = h->kinfo.num_desc;
if (old_desc_num == new_desc_num)
return 0;
netdev_info(ndev,
"Changing descriptor count from %d to %d.\n",
old_desc_num, new_desc_num);
if (if_running)
dev_close(ndev);
ret = hns3_uninit_all_ring(priv);
if (ret)
return ret;
ret = hns3_change_all_ring_bd_num(priv, new_desc_num);
if (ret) {
ret = hns3_change_all_ring_bd_num(priv, old_desc_num);
if (ret) {
netdev_err(ndev,
"Revert to old bd num fail, ret=%d.\n", ret);
return ret;
}
}
if (if_running)
ret = dev_open(ndev);
return ret;
}
static int hns3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
{
struct hnae3_handle *h = hns3_get_handle(netdev);
if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->set_rss_tuple)
return -EOPNOTSUPP;
switch (cmd->cmd) {
case ETHTOOL_SRXFH:
return h->ae_algo->ops->set_rss_tuple(h, cmd);
default:
return -EOPNOTSUPP;
}
}
static const struct ethtool_ops hns3_ethtool_ops = { static const struct ethtool_ops hns3_ethtool_ops = {
.get_drvinfo = hns3_get_drvinfo, .get_drvinfo = hns3_get_drvinfo,
.get_link = hns3_get_link, .get_link = hns3_get_link,
.get_ringparam = hns3_get_ringparam, .get_ringparam = hns3_get_ringparam,
.set_ringparam = hns3_set_ringparam,
.get_pauseparam = hns3_get_pauseparam, .get_pauseparam = hns3_get_pauseparam,
.get_strings = hns3_get_strings, .get_strings = hns3_get_strings,
.get_ethtool_stats = hns3_get_stats, .get_ethtool_stats = hns3_get_stats,
.get_sset_count = hns3_get_sset_count, .get_sset_count = hns3_get_sset_count,
.get_rxnfc = hns3_get_rxnfc, .get_rxnfc = hns3_get_rxnfc,
.set_rxnfc = hns3_set_rxnfc,
.get_rxfh_key_size = hns3_get_rss_key_size, .get_rxfh_key_size = hns3_get_rss_key_size,
.get_rxfh_indir_size = hns3_get_rss_indir_size, .get_rxfh_indir_size = hns3_get_rss_indir_size,
.get_rxfh = hns3_get_rss, .get_rxfh = hns3_get_rss,
......
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