Add support for ethtool_set_link_ksettings for mana.
Set speed information of the port using ethtool. This
feature is not supported by all hardware.

Before the change:
$ethtool -s enP30832s1 speed 100
>netlink error: Operation not supported
$ethtool enP30832s1
>Settings for enP30832s1:
        Supported ports: [  ]
        Supported link modes:   Not reported
        Supported pause frame use: No
        Supports auto-negotiation: No
        Supported FEC modes: Not reported
        Advertised link modes:  Not reported
        Advertised pause frame use: No
        Advertised auto-negotiation: No
        Advertised FEC modes: Not reported
        Speed: Unknown!
        Duplex: Full
        Auto-negotiation: off
        Port: Other
        PHYAD: 0
        Transceiver: internal
        Link detected: yes

After the change:
$ethtool -s enP30832s1 speed 100
$ethtool enP30832s1
>Settings for enP30832s1:
        Supported ports: [  ]
        Supported link modes:   Not reported
        Supported pause frame use: No
        Supports auto-negotiation: No
        Supported FEC modes: Not reported
        Advertised link modes:  Not reported
        Advertised pause frame use: No
        Advertised auto-negotiation: No
        Advertised FEC modes: Not reported
        Speed: 100Mb/s
        Duplex: Full
        Auto-negotiation: off
        Port: Other
        PHYAD: 0
        Transceiver: internal
        Link detected: yes

Signed-off-by: Erni Sri Satya Vennela <er...@linux.microsoft.com>
Reviewed-by: Haiyang Zhang <haiya...@microsoft.com>
Reviewed-by: Shradha Gupta <shradhagu...@linux.microsoft.com>
---
 drivers/net/ethernet/microsoft/mana/mana_en.c | 39 +++++++++++++++++++
 .../ethernet/microsoft/mana/mana_ethtool.c    | 13 +++++++
 include/net/mana/mana.h                       | 16 ++++++++
 3 files changed, 68 insertions(+)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c 
b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 5fa8e1e2ff9a..bcc273427423 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1203,6 +1203,45 @@ int mana_query_link_cfg(struct mana_port_context *apc)
        return err;
 }
 
+int mana_set_bw_clamp(struct mana_port_context *apc, u32 speed)
+{
+       struct mana_set_bw_clamp_req req = {};
+       struct mana_set_bw_clamp_resp resp = {};
+       struct net_device *ndev = apc->ndev;
+       int err;
+
+       mana_gd_init_req_hdr(&req.hdr, MANA_SET_BW_CLAMP,
+                            sizeof(req), sizeof(resp));
+       req.vport = apc->port_handle;
+       req.link_speed = speed;
+       req.enable_clamping = TRI_STATE_TRUE;
+
+       err = mana_send_request(apc->ac, &req, sizeof(req), &resp,
+                               sizeof(resp));
+
+       if (err) {
+               netdev_err(ndev, "Failed to set bandwidth clamp for speed %u, 
err = %d",
+                          speed, err);
+               return err;
+       }
+
+       err = mana_verify_resp_hdr(&resp.hdr, MANA_SET_BW_CLAMP,
+                                  sizeof(resp));
+
+       if (err || resp.hdr.status) {
+               netdev_err(ndev, "Failed to set bandwidth clamp: %d, 0x%x\n", 
err,
+                          resp.hdr.status);
+               if (!err)
+                       err = -EPROTO;
+               return err;
+       }
+
+       if (resp.qos_unconfigured)
+               netdev_info(ndev, "QoS is unconfigured\n");
+
+       return 0;
+}
+
 int mana_create_wq_obj(struct mana_port_context *apc,
                       mana_handle_t vport,
                       u32 wq_type, struct mana_obj_spec *wq_spec,
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c 
b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index 48234a738d26..b29d0fe0a201 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -439,6 +439,18 @@ static int mana_get_link_ksettings(struct net_device *ndev,
        return 0;
 }
 
+static int mana_set_link_ksettings(struct net_device *ndev,
+                                  const struct ethtool_link_ksettings *cmd)
+{
+       struct mana_port_context *apc = netdev_priv(ndev);
+       int err;
+
+       err = mana_set_bw_clamp(apc, cmd->base.speed);
+
+       apc->speed = (err) ? apc->speed : cmd->base.speed;
+       return 0;
+}
+
 const struct ethtool_ops mana_ethtool_ops = {
        .get_ethtool_stats      = mana_get_ethtool_stats,
        .get_sset_count         = mana_get_sset_count,
@@ -453,5 +465,6 @@ const struct ethtool_ops mana_ethtool_ops = {
        .get_ringparam          = mana_get_ringparam,
        .set_ringparam          = mana_set_ringparam,
        .get_link_ksettings     = mana_get_link_ksettings,
+       .set_link_ksettings     = mana_set_link_ksettings,
        .get_link               = ethtool_op_get_link,
 };
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 5f039ce99ade..b4c66ce9ee3a 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -500,6 +500,7 @@ void mana_chn_setxdp(struct mana_port_context *apc, struct 
bpf_prog *prog);
 int mana_bpf(struct net_device *ndev, struct netdev_bpf *bpf);
 void mana_query_gf_stats(struct mana_port_context *apc);
 int mana_query_link_cfg(struct mana_port_context *apc);
+int mana_set_bw_clamp(struct mana_port_context *apc, u32 speed);
 int mana_pre_alloc_rxbufs(struct mana_port_context *apc, int mtu, int 
num_queues);
 void mana_pre_dealloc_rxbufs(struct mana_port_context *apc);
 
@@ -527,6 +528,7 @@ enum mana_command_code {
        MANA_CONFIG_VPORT_RX    = 0x20007,
        MANA_QUERY_VPORT_CONFIG = 0x20008,
        MANA_QUERY_LINK_CONFIG  = 0x2000A,
+       MANA_SET_BW_CLAMP       = 0x2000B,
 
        /* Privileged commands for the PF mode */
        MANA_REGISTER_FILTER    = 0x28000,
@@ -548,6 +550,20 @@ struct mana_query_link_config_resp {
        u8 reserved[3];
 }; /* HW DATA */
 
+/* Set Bandwidth Clamp*/
+struct mana_set_bw_clamp_req {
+       struct gdma_req_hdr hdr;
+       mana_handle_t vport;
+       enum TRI_STATE enable_clamping;
+       u32 link_speed;
+}; /* HW DATA */
+
+struct mana_set_bw_clamp_resp {
+       struct gdma_resp_hdr hdr;
+       bool qos_unconfigured;
+       u8 reserved[7];
+}; /* HW DATA */
+
 /* Query Device Configuration */
 struct mana_query_device_cfg_req {
        struct gdma_req_hdr hdr;
-- 
2.34.1


Reply via email to