Skip to content

Commit cf11cf1

Browse files
author
Paolo Abeni
committed
Merge branch 'support-bandwidth-clamping-in-mana-using-net-shapers'
Erni Sri Satya Vennela says: ==================== Support bandwidth clamping in mana using net shapers This patchset introduces hardware-backed bandwidth rate limiting for MANA NICs via the net_shaper_ops interface, enabling efficient and fine-grained traffic shaping directly on the device. Previously, MANA lacked a mechanism for user-configurable bandwidth control. With this addition, users can now configure shaping parameters, allowing better traffic management and performance isolation. The implementation includes the net_shaper_ops callbacks in the MANA driver and supports one shaper per vport. Add shaping support via mana_set_bw_clamp(), allowing the configuration of bandwidth rates in 100 Mbps increments (minimum 100 Mbps). The driver validates input and rejects unsupported values. On failure, it restores the previous configuration which is queried using mana_query_link_cfg() or retains the current state. To prevent potential deadlocks introduced by net_shaper_ops, switch to _locked variants of NAPI APIs when netdevops_lock is held during VF setup and teardown. Also, Add support for ethtool get_link_ksettings to report the maximum link speed supported by the SKU in mbps. These APIs when invoked on hardware that are older or that do not support these APIs, the speed would be reported as UNKNOWN and the net-shaper calls to set speed would fail. ==================== Link: https://patch.msgid.link/1750144656-2021-1-git-send-email-ernis@linux.microsoft.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2 parents d3623dd + ca8ac48 commit cf11cf1

File tree

5 files changed

+239
-9
lines changed

5 files changed

+239
-9
lines changed

drivers/net/ethernet/microsoft/mana/hw_channel.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,10 @@ int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len,
891891
}
892892

893893
if (ctx->status_code && ctx->status_code != GDMA_STATUS_MORE_ENTRIES) {
894+
if (ctx->status_code == GDMA_STATUS_CMD_UNSUPPORTED) {
895+
err = -EOPNOTSUPP;
896+
goto out;
897+
}
894898
if (req_msg->req.msg_type != MANA_QUERY_PHY_STAT)
895899
dev_err(hwc->dev, "HWC: Failed hw_channel req: 0x%x\n",
896900
ctx->status_code);

drivers/net/ethernet/microsoft/mana/mana_en.c

Lines changed: 186 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,78 @@ static int mana_change_mtu(struct net_device *ndev, int new_mtu)
719719
return err;
720720
}
721721

722+
static int mana_shaper_set(struct net_shaper_binding *binding,
723+
const struct net_shaper *shaper,
724+
struct netlink_ext_ack *extack)
725+
{
726+
struct mana_port_context *apc = netdev_priv(binding->netdev);
727+
u32 old_speed, rate;
728+
int err;
729+
730+
if (shaper->handle.scope != NET_SHAPER_SCOPE_NETDEV) {
731+
NL_SET_ERR_MSG_MOD(extack, "net shaper scope should be netdev");
732+
return -EINVAL;
733+
}
734+
735+
if (apc->handle.id && shaper->handle.id != apc->handle.id) {
736+
NL_SET_ERR_MSG_MOD(extack, "Cannot create multiple shapers");
737+
return -EOPNOTSUPP;
738+
}
739+
740+
if (!shaper->bw_max || (shaper->bw_max % 100000000)) {
741+
NL_SET_ERR_MSG_MOD(extack, "Please use multiples of 100Mbps for bandwidth");
742+
return -EINVAL;
743+
}
744+
745+
rate = div_u64(shaper->bw_max, 1000); /* Convert bps to Kbps */
746+
rate = div_u64(rate, 1000); /* Convert Kbps to Mbps */
747+
748+
/* Get current speed */
749+
err = mana_query_link_cfg(apc);
750+
old_speed = (err) ? SPEED_UNKNOWN : apc->speed;
751+
752+
if (!err) {
753+
err = mana_set_bw_clamp(apc, rate, TRI_STATE_TRUE);
754+
apc->speed = (err) ? old_speed : rate;
755+
apc->handle = (err) ? apc->handle : shaper->handle;
756+
}
757+
758+
return err;
759+
}
760+
761+
static int mana_shaper_del(struct net_shaper_binding *binding,
762+
const struct net_shaper_handle *handle,
763+
struct netlink_ext_ack *extack)
764+
{
765+
struct mana_port_context *apc = netdev_priv(binding->netdev);
766+
int err;
767+
768+
err = mana_set_bw_clamp(apc, 0, TRI_STATE_FALSE);
769+
770+
if (!err) {
771+
/* Reset mana port context parameters */
772+
apc->handle.id = 0;
773+
apc->handle.scope = NET_SHAPER_SCOPE_UNSPEC;
774+
apc->speed = 0;
775+
}
776+
777+
return err;
778+
}
779+
780+
static void mana_shaper_cap(struct net_shaper_binding *binding,
781+
enum net_shaper_scope scope,
782+
unsigned long *flags)
783+
{
784+
*flags = BIT(NET_SHAPER_A_CAPS_SUPPORT_BW_MAX) |
785+
BIT(NET_SHAPER_A_CAPS_SUPPORT_METRIC_BPS);
786+
}
787+
788+
static const struct net_shaper_ops mana_shaper_ops = {
789+
.set = mana_shaper_set,
790+
.delete = mana_shaper_del,
791+
.capabilities = mana_shaper_cap,
792+
};
793+
722794
static const struct net_device_ops mana_devops = {
723795
.ndo_open = mana_open,
724796
.ndo_stop = mana_close,
@@ -729,6 +801,7 @@ static const struct net_device_ops mana_devops = {
729801
.ndo_bpf = mana_bpf,
730802
.ndo_xdp_xmit = mana_xdp_xmit,
731803
.ndo_change_mtu = mana_change_mtu,
804+
.net_shaper_ops = &mana_shaper_ops,
732805
};
733806

734807
static void mana_cleanup_port_context(struct mana_port_context *apc)
@@ -774,6 +847,9 @@ static int mana_send_request(struct mana_context *ac, void *in_buf,
774847
err = mana_gd_send_request(gc, in_len, in_buf, out_len,
775848
out_buf);
776849
if (err || resp->status) {
850+
if (err == -EOPNOTSUPP)
851+
return err;
852+
777853
if (req->req.msg_type != MANA_QUERY_PHY_STAT)
778854
dev_err(dev, "Failed to send mana message: %d, 0x%x\n",
779855
err, resp->status);
@@ -1162,6 +1238,95 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
11621238
return err;
11631239
}
11641240

1241+
int mana_query_link_cfg(struct mana_port_context *apc)
1242+
{
1243+
struct net_device *ndev = apc->ndev;
1244+
struct mana_query_link_config_resp resp = {};
1245+
struct mana_query_link_config_req req = {};
1246+
int err;
1247+
1248+
mana_gd_init_req_hdr(&req.hdr, MANA_QUERY_LINK_CONFIG,
1249+
sizeof(req), sizeof(resp));
1250+
1251+
req.vport = apc->port_handle;
1252+
req.hdr.resp.msg_version = GDMA_MESSAGE_V2;
1253+
1254+
err = mana_send_request(apc->ac, &req, sizeof(req), &resp,
1255+
sizeof(resp));
1256+
1257+
if (err) {
1258+
if (err == -EOPNOTSUPP) {
1259+
netdev_info_once(ndev, "MANA_QUERY_LINK_CONFIG not supported\n");
1260+
return err;
1261+
}
1262+
netdev_err(ndev, "Failed to query link config: %d\n", err);
1263+
return err;
1264+
}
1265+
1266+
err = mana_verify_resp_hdr(&resp.hdr, MANA_QUERY_LINK_CONFIG,
1267+
sizeof(resp));
1268+
1269+
if (err || resp.hdr.status) {
1270+
netdev_err(ndev, "Failed to query link config: %d, 0x%x\n", err,
1271+
resp.hdr.status);
1272+
if (!err)
1273+
err = -EOPNOTSUPP;
1274+
return err;
1275+
}
1276+
1277+
if (resp.qos_unconfigured) {
1278+
err = -EINVAL;
1279+
return err;
1280+
}
1281+
apc->speed = resp.link_speed_mbps;
1282+
apc->max_speed = resp.qos_speed_mbps;
1283+
return 0;
1284+
}
1285+
1286+
int mana_set_bw_clamp(struct mana_port_context *apc, u32 speed,
1287+
int enable_clamping)
1288+
{
1289+
struct mana_set_bw_clamp_resp resp = {};
1290+
struct mana_set_bw_clamp_req req = {};
1291+
struct net_device *ndev = apc->ndev;
1292+
int err;
1293+
1294+
mana_gd_init_req_hdr(&req.hdr, MANA_SET_BW_CLAMP,
1295+
sizeof(req), sizeof(resp));
1296+
req.vport = apc->port_handle;
1297+
req.link_speed_mbps = speed;
1298+
req.enable_clamping = enable_clamping;
1299+
1300+
err = mana_send_request(apc->ac, &req, sizeof(req), &resp,
1301+
sizeof(resp));
1302+
1303+
if (err) {
1304+
if (err == -EOPNOTSUPP) {
1305+
netdev_info_once(ndev, "MANA_SET_BW_CLAMP not supported\n");
1306+
return err;
1307+
}
1308+
netdev_err(ndev, "Failed to set bandwidth clamp for speed %u, err = %d",
1309+
speed, err);
1310+
return err;
1311+
}
1312+
1313+
err = mana_verify_resp_hdr(&resp.hdr, MANA_SET_BW_CLAMP,
1314+
sizeof(resp));
1315+
1316+
if (err || resp.hdr.status) {
1317+
netdev_err(ndev, "Failed to set bandwidth clamp: %d, 0x%x\n", err,
1318+
resp.hdr.status);
1319+
if (!err)
1320+
err = -EOPNOTSUPP;
1321+
return err;
1322+
}
1323+
1324+
if (resp.qos_unconfigured)
1325+
netdev_info(ndev, "QoS is unconfigured\n");
1326+
1327+
return 0;
1328+
}
1329+
11651330
int mana_create_wq_obj(struct mana_port_context *apc,
11661331
mana_handle_t vport,
11671332
u32 wq_type, struct mana_obj_spec *wq_spec,
@@ -1912,8 +2077,10 @@ static void mana_destroy_txq(struct mana_port_context *apc)
19122077
napi = &apc->tx_qp[i].tx_cq.napi;
19132078
if (apc->tx_qp[i].txq.napi_initialized) {
19142079
napi_synchronize(napi);
1915-
napi_disable(napi);
1916-
netif_napi_del(napi);
2080+
netdev_lock_ops_to_full(napi->dev);
2081+
napi_disable_locked(napi);
2082+
netif_napi_del_locked(napi);
2083+
netdev_unlock_full_to_ops(napi->dev);
19172084
apc->tx_qp[i].txq.napi_initialized = false;
19182085
}
19192086
mana_destroy_wq_obj(apc, GDMA_SQ, apc->tx_qp[i].tx_object);
@@ -2065,8 +2232,11 @@ static int mana_create_txq(struct mana_port_context *apc,
20652232

20662233
mana_create_txq_debugfs(apc, i);
20672234

2068-
netif_napi_add_tx(net, &cq->napi, mana_poll);
2069-
napi_enable(&cq->napi);
2235+
set_bit(NAPI_STATE_NO_BUSY_POLL, &cq->napi.state);
2236+
netdev_lock_ops_to_full(net);
2237+
netif_napi_add_locked(net, &cq->napi, mana_poll);
2238+
napi_enable_locked(&cq->napi);
2239+
netdev_unlock_full_to_ops(net);
20702240
txq->napi_initialized = true;
20712241

20722242
mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT);
@@ -2102,9 +2272,10 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
21022272
if (napi_initialized) {
21032273
napi_synchronize(napi);
21042274

2105-
napi_disable(napi);
2106-
2107-
netif_napi_del(napi);
2275+
netdev_lock_ops_to_full(napi->dev);
2276+
napi_disable_locked(napi);
2277+
netif_napi_del_locked(napi);
2278+
netdev_unlock_full_to_ops(napi->dev);
21082279
}
21092280
xdp_rxq_info_unreg(&rxq->xdp_rxq);
21102281

@@ -2355,14 +2526,18 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
23552526

23562527
gc->cq_table[cq->gdma_id] = cq->gdma_cq;
23572528

2358-
netif_napi_add_weight(ndev, &cq->napi, mana_poll, 1);
2529+
netdev_lock_ops_to_full(ndev);
2530+
netif_napi_add_weight_locked(ndev, &cq->napi, mana_poll, 1);
2531+
netdev_unlock_full_to_ops(ndev);
23592532

23602533
WARN_ON(xdp_rxq_info_reg(&rxq->xdp_rxq, ndev, rxq_idx,
23612534
cq->napi.napi_id));
23622535
WARN_ON(xdp_rxq_info_reg_mem_model(&rxq->xdp_rxq, MEM_TYPE_PAGE_POOL,
23632536
rxq->page_pool));
23642537

2365-
napi_enable(&cq->napi);
2538+
netdev_lock_ops_to_full(ndev);
2539+
napi_enable_locked(&cq->napi);
2540+
netdev_unlock_full_to_ops(ndev);
23662541

23672542
mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT);
23682543
out:
@@ -3001,6 +3176,8 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
30013176
goto free_indir;
30023177
}
30033178

3179+
debugfs_create_u32("current_speed", 0400, apc->mana_port_debugfs, &apc->speed);
3180+
30043181
return 0;
30053182

30063183
free_indir:

drivers/net/ethernet/microsoft/mana/mana_ethtool.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,12 @@ static int mana_set_ringparam(struct net_device *ndev,
495495
static int mana_get_link_ksettings(struct net_device *ndev,
496496
struct ethtool_link_ksettings *cmd)
497497
{
498+
struct mana_port_context *apc = netdev_priv(ndev);
499+
int err;
500+
501+
err = mana_query_link_cfg(apc);
502+
cmd->base.speed = (err) ? SPEED_UNKNOWN : apc->max_speed;
503+
498504
cmd->base.duplex = DUPLEX_FULL;
499505
cmd->base.port = PORT_OTHER;
500506

include/net/mana/gdma.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "shm_channel.h"
1111

1212
#define GDMA_STATUS_MORE_ENTRIES 0x00000105
13+
#define GDMA_STATUS_CMD_UNSUPPORTED 0xffffffff
1314

1415
/* Structures labeled with "HW DATA" are exchanged with the hardware. All of
1516
* them are naturally aligned and hence don't need __packed.

include/net/mana/mana.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define _MANA_H
66

77
#include <net/xdp.h>
8+
#include <net/net_shaper.h>
89

910
#include "gdma.h"
1011
#include "hw_channel.h"
@@ -526,7 +527,14 @@ struct mana_port_context {
526527
struct mutex vport_mutex;
527528
int vport_use_count;
528529

530+
/* Net shaper handle*/
531+
struct net_shaper_handle handle;
532+
529533
u16 port_idx;
534+
/* Currently configured speed (mbps) */
535+
u32 speed;
536+
/* Maximum speed supported by the SKU (mbps) */
537+
u32 max_speed;
530538

531539
bool port_is_up;
532540
bool port_st_save; /* Saved port state */
@@ -562,6 +570,9 @@ struct bpf_prog *mana_xdp_get(struct mana_port_context *apc);
562570
void mana_chn_setxdp(struct mana_port_context *apc, struct bpf_prog *prog);
563571
int mana_bpf(struct net_device *ndev, struct netdev_bpf *bpf);
564572
void mana_query_gf_stats(struct mana_port_context *apc);
573+
int mana_query_link_cfg(struct mana_port_context *apc);
574+
int mana_set_bw_clamp(struct mana_port_context *apc, u32 speed,
575+
int enable_clamping);
565576
void mana_query_phy_stats(struct mana_port_context *apc);
566577
int mana_pre_alloc_rxbufs(struct mana_port_context *apc, int mtu, int num_queues);
567578
void mana_pre_dealloc_rxbufs(struct mana_port_context *apc);
@@ -589,6 +600,8 @@ enum mana_command_code {
589600
MANA_FENCE_RQ = 0x20006,
590601
MANA_CONFIG_VPORT_RX = 0x20007,
591602
MANA_QUERY_VPORT_CONFIG = 0x20008,
603+
MANA_QUERY_LINK_CONFIG = 0x2000A,
604+
MANA_SET_BW_CLAMP = 0x2000B,
592605
MANA_QUERY_PHY_STAT = 0x2000c,
593606

594607
/* Privileged commands for the PF mode */
@@ -598,6 +611,35 @@ enum mana_command_code {
598611
MANA_DEREGISTER_HW_PORT = 0x28004,
599612
};
600613

614+
/* Query Link Configuration*/
615+
struct mana_query_link_config_req {
616+
struct gdma_req_hdr hdr;
617+
mana_handle_t vport;
618+
}; /* HW DATA */
619+
620+
struct mana_query_link_config_resp {
621+
struct gdma_resp_hdr hdr;
622+
u32 qos_speed_mbps;
623+
u8 qos_unconfigured;
624+
u8 reserved1[3];
625+
u32 link_speed_mbps;
626+
u8 reserved2[4];
627+
}; /* HW DATA */
628+
629+
/* Set Bandwidth Clamp*/
630+
struct mana_set_bw_clamp_req {
631+
struct gdma_req_hdr hdr;
632+
mana_handle_t vport;
633+
enum TRI_STATE enable_clamping;
634+
u32 link_speed_mbps;
635+
}; /* HW DATA */
636+
637+
struct mana_set_bw_clamp_resp {
638+
struct gdma_resp_hdr hdr;
639+
u8 qos_unconfigured;
640+
u8 reserved[7];
641+
}; /* HW DATA */
642+
601643
/* Query Device Configuration */
602644
struct mana_query_device_cfg_req {
603645
struct gdma_req_hdr hdr;

0 commit comments

Comments
 (0)