[PATCH v1 15/16] net-next/yunsilicon: Add ndo_set_mac_address
flat view
STALE649d
From: Xin Tian <hidden>
Date: 2024-12-18 10:51:08
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Add ndo_set_mac_address Co-developed-by: Honggang Wei <redacted> Co-developed-by: Lei Yan <redacted> Signed-off-by: Xin Tian <redacted> --- .../ethernet/yunsilicon/xsc/common/xsc_core.h | 2 + .../net/ethernet/yunsilicon/xsc/net/main.c | 22 ++++++ .../net/ethernet/yunsilicon/xsc/pci/vport.c | 72 +++++++++++++++++++ 3 files changed, 96 insertions(+)
diff --git a/drivers/net/ethernet/yunsilicon/xsc/common/xsc_core.h b/drivers/net/ethernet/yunsilicon/xsc/common/xsc_core.h
index d69be5352..5c60b3126 100644
--- a/drivers/net/ethernet/yunsilicon/xsc/common/xsc_core.h
+++ b/drivers/net/ethernet/yunsilicon/xsc/common/xsc_core.h@@ -612,6 +612,8 @@ int xsc_register_interface(struct xsc_interface *intf); void xsc_unregister_interface(struct xsc_interface *intf); u8 xsc_core_query_vport_state(struct xsc_core_device *xdev, u16 vport); +int xsc_core_modify_nic_vport_mac_address(struct xsc_core_device *xdev, + u16 vport, u8 *addr, bool perm_mac); static inline void *xsc_buf_offset(struct xsc_buf *buf, int offset) {
diff --git a/drivers/net/ethernet/yunsilicon/xsc/net/main.c b/drivers/net/ethernet/yunsilicon/xsc/net/main.c
index 0c6e949b5..6df7ed3bb 100644
--- a/drivers/net/ethernet/yunsilicon/xsc/net/main.c
+++ b/drivers/net/ethernet/yunsilicon/xsc/net/main.c@@ -1647,6 +1647,27 @@ static void xsc_eth_get_stats(struct net_device *netdev, struct rtnl_link_stats6 xsc_eth_fold_sw_stats64(adapter, stats); } +static int xsc_eth_set_mac(struct net_device *netdev, void *addr) +{ + struct xsc_adapter *adapter = netdev_priv(netdev); + struct sockaddr *saddr = addr; + struct xsc_core_device *xdev = adapter->xdev; + int ret; + + if (!is_valid_ether_addr(saddr->sa_data)) + return -EADDRNOTAVAIL; + + ret = xsc_core_modify_nic_vport_mac_address(xdev, 0, saddr->sa_data, false); + if (ret) + xsc_core_err(adapter->xdev, "%s: xsc set mac addr failed\n", __func__); + + netif_addr_lock_bh(netdev); + eth_hw_addr_set(netdev, saddr->sa_data); + netif_addr_unlock_bh(netdev); + + return 0; +} + static int xsc_eth_set_hw_mtu(struct xsc_core_device *xdev, u16 mtu, u16 rx_buf_sz) { struct xsc_set_mtu_mbox_in in;
@@ -1677,6 +1698,7 @@ static const struct net_device_ops xsc_netdev_ops = { .ndo_stop = xsc_eth_close, .ndo_start_xmit = xsc_eth_xmit_start, .ndo_get_stats64 = xsc_eth_get_stats, + .ndo_set_mac_address = xsc_eth_set_mac, }; static void xsc_eth_build_nic_netdev(struct xsc_adapter *adapter)
diff --git a/drivers/net/ethernet/yunsilicon/xsc/pci/vport.c b/drivers/net/ethernet/yunsilicon/xsc/pci/vport.c
index 8200f6c91..f044ac009 100644
--- a/drivers/net/ethernet/yunsilicon/xsc/pci/vport.c
+++ b/drivers/net/ethernet/yunsilicon/xsc/pci/vport.c@@ -6,6 +6,8 @@ #include "common/xsc_core.h" #include "common/xsc_driver.h" +#define LAG_ID_INVALID U16_MAX + u8 xsc_core_query_vport_state(struct xsc_core_device *xdev, u16 vport) { struct xsc_query_vport_state_in in;
@@ -28,3 +30,73 @@ u8 xsc_core_query_vport_state(struct xsc_core_device *xdev, u16 vport) return out.state; } EXPORT_SYMBOL(xsc_core_query_vport_state); + +static int xsc_modify_nic_vport_context(struct xsc_core_device *xdev, void *in, + int inlen) +{ + struct xsc_modify_nic_vport_context_out out; + struct xsc_modify_nic_vport_context_in *tmp; + int err; + + memset(&out, 0, sizeof(out)); + tmp = (struct xsc_modify_nic_vport_context_in *)in; + tmp->hdr.opcode = cpu_to_be16(XSC_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); + + err = xsc_cmd_exec(xdev, in, inlen, &out, sizeof(out)); + if (err || out.hdr.status) { + xsc_core_err(xdev, "fail to modify nic vport err=%d status=%d\n", + err, out.hdr.status); + } + return err; +} + +static int __xsc_modify_nic_vport_mac_address(struct xsc_core_device *xdev, + u16 vport, u8 *addr, int force_other, bool perm_mac) +{ + struct xsc_modify_nic_vport_context_in *in; + int err; + int in_sz; + u8 *mac_addr; + u16 caps = 0; + u16 caps_mask = 0; + u16 lag_id = LAG_ID_INVALID; + + in_sz = sizeof(struct xsc_modify_nic_vport_context_in) + 2; + + in = kzalloc(in_sz, GFP_KERNEL); + if (!in) + return -ENOMEM; + + in->lag_id = cpu_to_be16(lag_id); + + if (perm_mac) { + in->field_select.permanent_address = 1; + mac_addr = in->nic_vport_ctx.permanent_address; + } else { + in->field_select.current_address = 1; + mac_addr = in->nic_vport_ctx.current_address; + } + + caps_mask |= BIT(XSC_TBM_CAP_PP_BYPASS); + in->caps = cpu_to_be16(caps); + in->caps_mask = cpu_to_be16(caps_mask); + + ether_addr_copy(mac_addr, addr); + + in->field_select.addresses_list = 1; + in->nic_vport_ctx.vlan_allowed = 0; + + err = xsc_modify_nic_vport_context(xdev, in, in_sz); + if (err) + xsc_core_err(xdev, "modify nic vport context failed\n"); + + kfree(in); + return err; +} + +int xsc_core_modify_nic_vport_mac_address(struct xsc_core_device *xdev, + u16 vport, u8 *addr, bool perm_mac) +{ + return __xsc_modify_nic_vport_mac_address(xdev, vport, addr, 0, perm_mac); +} +EXPORT_SYMBOL(xsc_core_modify_nic_vport_mac_address);
--
2.43.0