Skip to content

Commit 36d8afb

Browse files
committed
Merge branch 'idpf-add-get-set-for-ethtool-s-header-split-ringparam'
Alexander Lobakin says: ==================== idpf: add get/set for Ethtool's header split ringparam Currently, the header split feature (putting headers in one smaller buffer and then the data in a separate bigger one) is always enabled in idpf when supported. One may want to not have fragmented frames per each packet, for example, to avoid XDP frags. To better optimize setups for particular workloads, add ability to switch the header split state on and off via Ethtool's ringparams, as well as to query the current status. There's currently only GET in the Ethtool Netlink interface for now, so add SET first. I suspect idpf is not the only one supporting this. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 173b6d1 + 9b1aa3e commit 36d8afb

File tree

7 files changed

+104
-7
lines changed

7 files changed

+104
-7
lines changed

drivers/net/ethernet/intel/idpf/idpf.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct idpf_vport_max_q;
1515
#include <linux/pci.h>
1616
#include <linux/bitfield.h>
1717
#include <linux/sctp.h>
18-
#include <linux/ethtool.h>
18+
#include <linux/ethtool_netlink.h>
1919
#include <net/gro.h>
2020
#include <linux/dim.h>
2121

@@ -418,11 +418,13 @@ struct idpf_vport {
418418

419419
/**
420420
* enum idpf_user_flags
421+
* @__IDPF_USER_FLAG_HSPLIT: header split state
421422
* @__IDPF_PROMISC_UC: Unicast promiscuous mode
422423
* @__IDPF_PROMISC_MC: Multicast promiscuous mode
423424
* @__IDPF_USER_FLAGS_NBITS: Must be last
424425
*/
425426
enum idpf_user_flags {
427+
__IDPF_USER_FLAG_HSPLIT = 0U,
426428
__IDPF_PROMISC_UC = 32,
427429
__IDPF_PROMISC_MC,
428430

@@ -965,4 +967,7 @@ int idpf_send_map_unmap_queue_vector_msg(struct idpf_vport *vport, bool map);
965967
int idpf_send_set_sriov_vfs_msg(struct idpf_adapter *adapter, u16 num_vfs);
966968
int idpf_sriov_configure(struct pci_dev *pdev, int num_vfs);
967969

970+
u8 idpf_vport_get_hsplit(const struct idpf_vport *vport);
971+
bool idpf_vport_set_hsplit(const struct idpf_vport *vport, u8 val);
972+
968973
#endif /* !_IDPF_H_ */

drivers/net/ethernet/intel/idpf/idpf_ethtool.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,8 @@ static void idpf_get_ringparam(struct net_device *netdev,
320320
ring->rx_pending = vport->rxq_desc_count;
321321
ring->tx_pending = vport->txq_desc_count;
322322

323+
kring->tcp_data_split = idpf_vport_get_hsplit(vport);
324+
323325
idpf_vport_ctrl_unlock(netdev);
324326
}
325327

@@ -379,6 +381,14 @@ static int idpf_set_ringparam(struct net_device *netdev,
379381
new_rx_count == vport->rxq_desc_count)
380382
goto unlock_mutex;
381383

384+
if (!idpf_vport_set_hsplit(vport, kring->tcp_data_split)) {
385+
NL_SET_ERR_MSG_MOD(ext_ack,
386+
"setting TCP data split is not supported");
387+
err = -EOPNOTSUPP;
388+
389+
goto unlock_mutex;
390+
}
391+
382392
config_data = &vport->adapter->vport_config[idx]->user_config;
383393
config_data->num_req_txq_desc = new_tx_count;
384394
config_data->num_req_rxq_desc = new_rx_count;
@@ -1334,6 +1344,7 @@ static int idpf_get_link_ksettings(struct net_device *netdev,
13341344
static const struct ethtool_ops idpf_ethtool_ops = {
13351345
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
13361346
ETHTOOL_COALESCE_USE_ADAPTIVE,
1347+
.supported_ring_params = ETHTOOL_RING_USE_TCP_DATA_SPLIT,
13371348
.get_msglevel = idpf_get_msglevel,
13381349
.set_msglevel = idpf_set_msglevel,
13391350
.get_link = ethtool_op_get_link,

drivers/net/ethernet/intel/idpf/idpf_lib.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,71 @@ static void idpf_vport_dealloc(struct idpf_vport *vport)
10571057
adapter->next_vport = idpf_get_free_slot(adapter);
10581058
}
10591059

1060+
/**
1061+
* idpf_is_hsplit_supported - check whether the header split is supported
1062+
* @vport: virtual port to check the capability for
1063+
*
1064+
* Return: true if it's supported by the HW/FW, false if not.
1065+
*/
1066+
static bool idpf_is_hsplit_supported(const struct idpf_vport *vport)
1067+
{
1068+
return idpf_is_queue_model_split(vport->rxq_model) &&
1069+
idpf_is_cap_ena_all(vport->adapter, IDPF_HSPLIT_CAPS,
1070+
IDPF_CAP_HSPLIT);
1071+
}
1072+
1073+
/**
1074+
* idpf_vport_get_hsplit - get the current header split feature state
1075+
* @vport: virtual port to query the state for
1076+
*
1077+
* Return: ``ETHTOOL_TCP_DATA_SPLIT_UNKNOWN`` if not supported,
1078+
* ``ETHTOOL_TCP_DATA_SPLIT_DISABLED`` if disabled,
1079+
* ``ETHTOOL_TCP_DATA_SPLIT_ENABLED`` if active.
1080+
*/
1081+
u8 idpf_vport_get_hsplit(const struct idpf_vport *vport)
1082+
{
1083+
const struct idpf_vport_user_config_data *config;
1084+
1085+
if (!idpf_is_hsplit_supported(vport))
1086+
return ETHTOOL_TCP_DATA_SPLIT_UNKNOWN;
1087+
1088+
config = &vport->adapter->vport_config[vport->idx]->user_config;
1089+
1090+
return test_bit(__IDPF_USER_FLAG_HSPLIT, config->user_flags) ?
1091+
ETHTOOL_TCP_DATA_SPLIT_ENABLED :
1092+
ETHTOOL_TCP_DATA_SPLIT_DISABLED;
1093+
}
1094+
1095+
/**
1096+
* idpf_vport_set_hsplit - enable or disable header split on a given vport
1097+
* @vport: virtual port to configure
1098+
* @val: Ethtool flag controlling the header split state
1099+
*
1100+
* Return: true on success, false if not supported by the HW.
1101+
*/
1102+
bool idpf_vport_set_hsplit(const struct idpf_vport *vport, u8 val)
1103+
{
1104+
struct idpf_vport_user_config_data *config;
1105+
1106+
if (!idpf_is_hsplit_supported(vport))
1107+
return val == ETHTOOL_TCP_DATA_SPLIT_UNKNOWN;
1108+
1109+
config = &vport->adapter->vport_config[vport->idx]->user_config;
1110+
1111+
switch (val) {
1112+
case ETHTOOL_TCP_DATA_SPLIT_UNKNOWN:
1113+
/* Default is to enable */
1114+
case ETHTOOL_TCP_DATA_SPLIT_ENABLED:
1115+
__set_bit(__IDPF_USER_FLAG_HSPLIT, config->user_flags);
1116+
return true;
1117+
case ETHTOOL_TCP_DATA_SPLIT_DISABLED:
1118+
__clear_bit(__IDPF_USER_FLAG_HSPLIT, config->user_flags);
1119+
return true;
1120+
default:
1121+
return false;
1122+
}
1123+
}
1124+
10601125
/**
10611126
* idpf_vport_alloc - Allocates the next available struct vport in the adapter
10621127
* @adapter: board private structure

drivers/net/ethernet/intel/idpf/idpf_txrx.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,12 +1240,15 @@ static int idpf_rxq_group_alloc(struct idpf_vport *vport, u16 num_rxq)
12401240
struct idpf_adapter *adapter = vport->adapter;
12411241
struct idpf_queue *q;
12421242
int i, k, err = 0;
1243+
bool hs;
12431244

12441245
vport->rxq_grps = kcalloc(vport->num_rxq_grp,
12451246
sizeof(struct idpf_rxq_group), GFP_KERNEL);
12461247
if (!vport->rxq_grps)
12471248
return -ENOMEM;
12481249

1250+
hs = idpf_vport_get_hsplit(vport) == ETHTOOL_TCP_DATA_SPLIT_ENABLED;
1251+
12491252
for (i = 0; i < vport->num_rxq_grp; i++) {
12501253
struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];
12511254
int j;
@@ -1298,9 +1301,8 @@ static int idpf_rxq_group_alloc(struct idpf_vport *vport, u16 num_rxq)
12981301
q->rx_buf_size = vport->bufq_size[j];
12991302
q->rx_buffer_low_watermark = IDPF_LOW_WATERMARK;
13001303
q->rx_buf_stride = IDPF_RX_BUF_STRIDE;
1301-
if (idpf_is_cap_ena_all(adapter, IDPF_HSPLIT_CAPS,
1302-
IDPF_CAP_HSPLIT) &&
1303-
idpf_is_queue_model_split(vport->rxq_model)) {
1304+
1305+
if (hs) {
13041306
q->rx_hsplit_en = true;
13051307
q->rx_hbuf_size = IDPF_HDR_BUF_SIZE;
13061308
}
@@ -1344,9 +1346,7 @@ static int idpf_rxq_group_alloc(struct idpf_vport *vport, u16 num_rxq)
13441346
rx_qgrp->splitq.rxq_sets[j]->refillq1 =
13451347
&rx_qgrp->splitq.bufq_sets[1].refillqs[j];
13461348

1347-
if (idpf_is_cap_ena_all(adapter, IDPF_HSPLIT_CAPS,
1348-
IDPF_CAP_HSPLIT) &&
1349-
idpf_is_queue_model_split(vport->rxq_model)) {
1349+
if (hs) {
13501350
q->rx_hsplit_en = true;
13511351
q->rx_hbuf_size = IDPF_HDR_BUF_SIZE;
13521352
}

drivers/net/ethernet/intel/idpf/idpf_virtchnl.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3285,6 +3285,8 @@ void idpf_vport_init(struct idpf_vport *vport, struct idpf_vport_max_q *max_q)
32853285
memcpy(vport->rx_itr_profile, rx_itr, IDPF_DIM_PROFILE_SLOTS);
32863286
memcpy(vport->tx_itr_profile, tx_itr, IDPF_DIM_PROFILE_SLOTS);
32873287

3288+
idpf_vport_set_hsplit(vport, ETHTOOL_TCP_DATA_SPLIT_ENABLED);
3289+
32883290
idpf_vport_init_num_qs(vport, vport_msg);
32893291
idpf_vport_calc_num_q_desc(vport);
32903292
idpf_vport_calc_num_q_groups(vport);

include/linux/ethtool.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,15 @@ struct kernel_ethtool_ringparam {
9595
* @ETHTOOL_RING_USE_TX_PUSH: capture for setting tx_push
9696
* @ETHTOOL_RING_USE_RX_PUSH: capture for setting rx_push
9797
* @ETHTOOL_RING_USE_TX_PUSH_BUF_LEN: capture for setting tx_push_buf_len
98+
* @ETHTOOL_RING_USE_TCP_DATA_SPLIT: capture for setting tcp_data_split
9899
*/
99100
enum ethtool_supported_ring_param {
100101
ETHTOOL_RING_USE_RX_BUF_LEN = BIT(0),
101102
ETHTOOL_RING_USE_CQE_SIZE = BIT(1),
102103
ETHTOOL_RING_USE_TX_PUSH = BIT(2),
103104
ETHTOOL_RING_USE_RX_PUSH = BIT(3),
104105
ETHTOOL_RING_USE_TX_PUSH_BUF_LEN = BIT(4),
106+
ETHTOOL_RING_USE_TCP_DATA_SPLIT = BIT(5),
105107
};
106108

107109
#define __ETH_RSS_HASH_BIT(bit) ((u32)1 << (bit))

net/ethtool/rings.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ const struct nla_policy ethnl_rings_set_policy[] = {
124124
[ETHTOOL_A_RINGS_RX_JUMBO] = { .type = NLA_U32 },
125125
[ETHTOOL_A_RINGS_TX] = { .type = NLA_U32 },
126126
[ETHTOOL_A_RINGS_RX_BUF_LEN] = NLA_POLICY_MIN(NLA_U32, 1),
127+
[ETHTOOL_A_RINGS_TCP_DATA_SPLIT] =
128+
NLA_POLICY_MAX(NLA_U8, ETHTOOL_TCP_DATA_SPLIT_ENABLED),
127129
[ETHTOOL_A_RINGS_CQE_SIZE] = NLA_POLICY_MIN(NLA_U32, 1),
128130
[ETHTOOL_A_RINGS_TX_PUSH] = NLA_POLICY_MAX(NLA_U8, 1),
129131
[ETHTOOL_A_RINGS_RX_PUSH] = NLA_POLICY_MAX(NLA_U8, 1),
@@ -145,6 +147,14 @@ ethnl_set_rings_validate(struct ethnl_req_info *req_info,
145147
return -EOPNOTSUPP;
146148
}
147149

150+
if (tb[ETHTOOL_A_RINGS_TCP_DATA_SPLIT] &&
151+
!(ops->supported_ring_params & ETHTOOL_RING_USE_TCP_DATA_SPLIT)) {
152+
NL_SET_ERR_MSG_ATTR(info->extack,
153+
tb[ETHTOOL_A_RINGS_TCP_DATA_SPLIT],
154+
"setting TCP data split is not supported");
155+
return -EOPNOTSUPP;
156+
}
157+
148158
if (tb[ETHTOOL_A_RINGS_CQE_SIZE] &&
149159
!(ops->supported_ring_params & ETHTOOL_RING_USE_CQE_SIZE)) {
150160
NL_SET_ERR_MSG_ATTR(info->extack,
@@ -202,6 +212,8 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info)
202212
ethnl_update_u32(&ringparam.tx_pending, tb[ETHTOOL_A_RINGS_TX], &mod);
203213
ethnl_update_u32(&kernel_ringparam.rx_buf_len,
204214
tb[ETHTOOL_A_RINGS_RX_BUF_LEN], &mod);
215+
ethnl_update_u8(&kernel_ringparam.tcp_data_split,
216+
tb[ETHTOOL_A_RINGS_TCP_DATA_SPLIT], &mod);
205217
ethnl_update_u32(&kernel_ringparam.cqe_size,
206218
tb[ETHTOOL_A_RINGS_CQE_SIZE], &mod);
207219
ethnl_update_u8(&kernel_ringparam.tx_push,

0 commit comments

Comments
 (0)