1*17fcb3dcSFan Gong // SPDX-License-Identifier: GPL-2.0 2*17fcb3dcSFan Gong // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3*17fcb3dcSFan Gong 4*17fcb3dcSFan Gong #include <linux/if_vlan.h> 5*17fcb3dcSFan Gong 6*17fcb3dcSFan Gong #include "hinic3_hwdev.h" 7*17fcb3dcSFan Gong #include "hinic3_hwif.h" 8*17fcb3dcSFan Gong #include "hinic3_mbox.h" 9*17fcb3dcSFan Gong #include "hinic3_nic_cfg.h" 10*17fcb3dcSFan Gong #include "hinic3_nic_dev.h" 11*17fcb3dcSFan Gong #include "hinic3_nic_io.h" 12*17fcb3dcSFan Gong 13*17fcb3dcSFan Gong static int hinic3_feature_nego(struct hinic3_hwdev *hwdev, u8 opcode, 14*17fcb3dcSFan Gong u64 *s_feature, u16 size) 15*17fcb3dcSFan Gong { 16*17fcb3dcSFan Gong struct l2nic_cmd_feature_nego feature_nego = {}; 17*17fcb3dcSFan Gong struct mgmt_msg_params msg_params = {}; 18*17fcb3dcSFan Gong int err; 19*17fcb3dcSFan Gong 20*17fcb3dcSFan Gong feature_nego.func_id = hinic3_global_func_id(hwdev); 21*17fcb3dcSFan Gong feature_nego.opcode = opcode; 22*17fcb3dcSFan Gong if (opcode == MGMT_MSG_CMD_OP_SET) 23*17fcb3dcSFan Gong memcpy(feature_nego.s_feature, s_feature, size * sizeof(u64)); 24*17fcb3dcSFan Gong 25*17fcb3dcSFan Gong mgmt_msg_params_init_default(&msg_params, &feature_nego, 26*17fcb3dcSFan Gong sizeof(feature_nego)); 27*17fcb3dcSFan Gong 28*17fcb3dcSFan Gong err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 29*17fcb3dcSFan Gong L2NIC_CMD_FEATURE_NEGO, &msg_params); 30*17fcb3dcSFan Gong if (err || feature_nego.msg_head.status) { 31*17fcb3dcSFan Gong dev_err(hwdev->dev, "Failed to negotiate nic feature, err:%d, status: 0x%x\n", 32*17fcb3dcSFan Gong err, feature_nego.msg_head.status); 33*17fcb3dcSFan Gong return -EIO; 34*17fcb3dcSFan Gong } 35*17fcb3dcSFan Gong 36*17fcb3dcSFan Gong if (opcode == MGMT_MSG_CMD_OP_GET) 37*17fcb3dcSFan Gong memcpy(s_feature, feature_nego.s_feature, size * sizeof(u64)); 38*17fcb3dcSFan Gong 39*17fcb3dcSFan Gong return 0; 40*17fcb3dcSFan Gong } 41*17fcb3dcSFan Gong 42*17fcb3dcSFan Gong int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev) 43*17fcb3dcSFan Gong { 44*17fcb3dcSFan Gong return hinic3_feature_nego(nic_dev->hwdev, MGMT_MSG_CMD_OP_SET, 45*17fcb3dcSFan Gong &nic_dev->nic_io->feature_cap, 1); 46*17fcb3dcSFan Gong } 47*17fcb3dcSFan Gong 48*17fcb3dcSFan Gong bool hinic3_test_support(struct hinic3_nic_dev *nic_dev, 49*17fcb3dcSFan Gong enum hinic3_nic_feature_cap feature_bits) 50*17fcb3dcSFan Gong { 51*17fcb3dcSFan Gong return (nic_dev->nic_io->feature_cap & feature_bits) == feature_bits; 52*17fcb3dcSFan Gong } 53*17fcb3dcSFan Gong 54*17fcb3dcSFan Gong void hinic3_update_nic_feature(struct hinic3_nic_dev *nic_dev, u64 feature_cap) 55*17fcb3dcSFan Gong { 56*17fcb3dcSFan Gong nic_dev->nic_io->feature_cap = feature_cap; 57*17fcb3dcSFan Gong } 58*17fcb3dcSFan Gong 59*17fcb3dcSFan Gong static int hinic3_set_function_table(struct hinic3_hwdev *hwdev, u32 cfg_bitmap, 60*17fcb3dcSFan Gong const struct l2nic_func_tbl_cfg *cfg) 61*17fcb3dcSFan Gong { 62*17fcb3dcSFan Gong struct l2nic_cmd_set_func_tbl cmd_func_tbl = {}; 63*17fcb3dcSFan Gong struct mgmt_msg_params msg_params = {}; 64*17fcb3dcSFan Gong int err; 65*17fcb3dcSFan Gong 66*17fcb3dcSFan Gong cmd_func_tbl.func_id = hinic3_global_func_id(hwdev); 67*17fcb3dcSFan Gong cmd_func_tbl.cfg_bitmap = cfg_bitmap; 68*17fcb3dcSFan Gong cmd_func_tbl.tbl_cfg = *cfg; 69*17fcb3dcSFan Gong 70*17fcb3dcSFan Gong mgmt_msg_params_init_default(&msg_params, &cmd_func_tbl, 71*17fcb3dcSFan Gong sizeof(cmd_func_tbl)); 72*17fcb3dcSFan Gong 73*17fcb3dcSFan Gong err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 74*17fcb3dcSFan Gong L2NIC_CMD_SET_FUNC_TBL, &msg_params); 75*17fcb3dcSFan Gong if (err || cmd_func_tbl.msg_head.status) { 76*17fcb3dcSFan Gong dev_err(hwdev->dev, 77*17fcb3dcSFan Gong "Failed to set func table, bitmap: 0x%x, err: %d, status: 0x%x\n", 78*17fcb3dcSFan Gong cfg_bitmap, err, cmd_func_tbl.msg_head.status); 79*17fcb3dcSFan Gong return -EFAULT; 80*17fcb3dcSFan Gong } 81*17fcb3dcSFan Gong 82*17fcb3dcSFan Gong return 0; 83*17fcb3dcSFan Gong } 84*17fcb3dcSFan Gong 85*17fcb3dcSFan Gong int hinic3_set_port_mtu(struct net_device *netdev, u16 new_mtu) 86*17fcb3dcSFan Gong { 87*17fcb3dcSFan Gong struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 88*17fcb3dcSFan Gong struct l2nic_func_tbl_cfg func_tbl_cfg = {}; 89*17fcb3dcSFan Gong struct hinic3_hwdev *hwdev = nic_dev->hwdev; 90*17fcb3dcSFan Gong 91*17fcb3dcSFan Gong func_tbl_cfg.mtu = new_mtu; 92*17fcb3dcSFan Gong return hinic3_set_function_table(hwdev, BIT(L2NIC_FUNC_TBL_CFG_MTU), 93*17fcb3dcSFan Gong &func_tbl_cfg); 94*17fcb3dcSFan Gong } 95*17fcb3dcSFan Gong 96*17fcb3dcSFan Gong static int hinic3_check_mac_info(struct hinic3_hwdev *hwdev, u8 status, 97*17fcb3dcSFan Gong u16 vlan_id) 98*17fcb3dcSFan Gong { 99*17fcb3dcSFan Gong if ((status && status != MGMT_STATUS_EXIST) || 100*17fcb3dcSFan Gong ((vlan_id & BIT(15)) && status == MGMT_STATUS_EXIST)) { 101*17fcb3dcSFan Gong return -EINVAL; 102*17fcb3dcSFan Gong } 103*17fcb3dcSFan Gong 104*17fcb3dcSFan Gong return 0; 105*17fcb3dcSFan Gong } 106*17fcb3dcSFan Gong 107*17fcb3dcSFan Gong int hinic3_set_mac(struct hinic3_hwdev *hwdev, const u8 *mac_addr, u16 vlan_id, 108*17fcb3dcSFan Gong u16 func_id) 109*17fcb3dcSFan Gong { 110*17fcb3dcSFan Gong struct l2nic_cmd_set_mac mac_info = {}; 111*17fcb3dcSFan Gong struct mgmt_msg_params msg_params = {}; 112*17fcb3dcSFan Gong int err; 113*17fcb3dcSFan Gong 114*17fcb3dcSFan Gong if ((vlan_id & HINIC3_VLAN_ID_MASK) >= VLAN_N_VID) { 115*17fcb3dcSFan Gong dev_err(hwdev->dev, "Invalid VLAN number: %d\n", 116*17fcb3dcSFan Gong (vlan_id & HINIC3_VLAN_ID_MASK)); 117*17fcb3dcSFan Gong return -EINVAL; 118*17fcb3dcSFan Gong } 119*17fcb3dcSFan Gong 120*17fcb3dcSFan Gong mac_info.func_id = func_id; 121*17fcb3dcSFan Gong mac_info.vlan_id = vlan_id; 122*17fcb3dcSFan Gong ether_addr_copy(mac_info.mac, mac_addr); 123*17fcb3dcSFan Gong 124*17fcb3dcSFan Gong mgmt_msg_params_init_default(&msg_params, &mac_info, sizeof(mac_info)); 125*17fcb3dcSFan Gong 126*17fcb3dcSFan Gong err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 127*17fcb3dcSFan Gong L2NIC_CMD_SET_MAC, &msg_params); 128*17fcb3dcSFan Gong if (err || hinic3_check_mac_info(hwdev, mac_info.msg_head.status, 129*17fcb3dcSFan Gong mac_info.vlan_id)) { 130*17fcb3dcSFan Gong dev_err(hwdev->dev, 131*17fcb3dcSFan Gong "Failed to update MAC, err: %d, status: 0x%x\n", 132*17fcb3dcSFan Gong err, mac_info.msg_head.status); 133*17fcb3dcSFan Gong return -EIO; 134*17fcb3dcSFan Gong } 135*17fcb3dcSFan Gong 136*17fcb3dcSFan Gong if (mac_info.msg_head.status == MGMT_STATUS_PF_SET_VF_ALREADY) { 137*17fcb3dcSFan Gong dev_warn(hwdev->dev, "PF has already set VF mac, Ignore set operation\n"); 138*17fcb3dcSFan Gong return 0; 139*17fcb3dcSFan Gong } 140*17fcb3dcSFan Gong 141*17fcb3dcSFan Gong if (mac_info.msg_head.status == MGMT_STATUS_EXIST) { 142*17fcb3dcSFan Gong dev_warn(hwdev->dev, "MAC is repeated. Ignore update operation\n"); 143*17fcb3dcSFan Gong return 0; 144*17fcb3dcSFan Gong } 145*17fcb3dcSFan Gong 146*17fcb3dcSFan Gong return 0; 147*17fcb3dcSFan Gong } 148*17fcb3dcSFan Gong 149*17fcb3dcSFan Gong int hinic3_del_mac(struct hinic3_hwdev *hwdev, const u8 *mac_addr, u16 vlan_id, 150*17fcb3dcSFan Gong u16 func_id) 151*17fcb3dcSFan Gong { 152*17fcb3dcSFan Gong struct l2nic_cmd_set_mac mac_info = {}; 153*17fcb3dcSFan Gong struct mgmt_msg_params msg_params = {}; 154*17fcb3dcSFan Gong int err; 155*17fcb3dcSFan Gong 156*17fcb3dcSFan Gong if ((vlan_id & HINIC3_VLAN_ID_MASK) >= VLAN_N_VID) { 157*17fcb3dcSFan Gong dev_err(hwdev->dev, "Invalid VLAN number: %d\n", 158*17fcb3dcSFan Gong (vlan_id & HINIC3_VLAN_ID_MASK)); 159*17fcb3dcSFan Gong return -EINVAL; 160*17fcb3dcSFan Gong } 161*17fcb3dcSFan Gong 162*17fcb3dcSFan Gong mac_info.func_id = func_id; 163*17fcb3dcSFan Gong mac_info.vlan_id = vlan_id; 164*17fcb3dcSFan Gong ether_addr_copy(mac_info.mac, mac_addr); 165*17fcb3dcSFan Gong 166*17fcb3dcSFan Gong mgmt_msg_params_init_default(&msg_params, &mac_info, sizeof(mac_info)); 167*17fcb3dcSFan Gong 168*17fcb3dcSFan Gong err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 169*17fcb3dcSFan Gong L2NIC_CMD_DEL_MAC, &msg_params); 170*17fcb3dcSFan Gong if (err) { 171*17fcb3dcSFan Gong dev_err(hwdev->dev, 172*17fcb3dcSFan Gong "Failed to delete MAC, err: %d, status: 0x%x\n", 173*17fcb3dcSFan Gong err, mac_info.msg_head.status); 174*17fcb3dcSFan Gong return err; 175*17fcb3dcSFan Gong } 176*17fcb3dcSFan Gong 177*17fcb3dcSFan Gong return 0; 178*17fcb3dcSFan Gong } 179*17fcb3dcSFan Gong 180*17fcb3dcSFan Gong int hinic3_update_mac(struct hinic3_hwdev *hwdev, const u8 *old_mac, 181*17fcb3dcSFan Gong u8 *new_mac, u16 vlan_id, u16 func_id) 182*17fcb3dcSFan Gong { 183*17fcb3dcSFan Gong struct l2nic_cmd_update_mac mac_info = {}; 184*17fcb3dcSFan Gong struct mgmt_msg_params msg_params = {}; 185*17fcb3dcSFan Gong int err; 186*17fcb3dcSFan Gong 187*17fcb3dcSFan Gong if ((vlan_id & HINIC3_VLAN_ID_MASK) >= VLAN_N_VID) { 188*17fcb3dcSFan Gong dev_err(hwdev->dev, "Invalid VLAN number: %d\n", 189*17fcb3dcSFan Gong (vlan_id & HINIC3_VLAN_ID_MASK)); 190*17fcb3dcSFan Gong return -EINVAL; 191*17fcb3dcSFan Gong } 192*17fcb3dcSFan Gong 193*17fcb3dcSFan Gong mac_info.func_id = func_id; 194*17fcb3dcSFan Gong mac_info.vlan_id = vlan_id; 195*17fcb3dcSFan Gong ether_addr_copy(mac_info.old_mac, old_mac); 196*17fcb3dcSFan Gong ether_addr_copy(mac_info.new_mac, new_mac); 197*17fcb3dcSFan Gong 198*17fcb3dcSFan Gong mgmt_msg_params_init_default(&msg_params, &mac_info, sizeof(mac_info)); 199*17fcb3dcSFan Gong 200*17fcb3dcSFan Gong err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 201*17fcb3dcSFan Gong L2NIC_CMD_UPDATE_MAC, &msg_params); 202*17fcb3dcSFan Gong if (err || hinic3_check_mac_info(hwdev, mac_info.msg_head.status, 203*17fcb3dcSFan Gong mac_info.vlan_id)) { 204*17fcb3dcSFan Gong dev_err(hwdev->dev, 205*17fcb3dcSFan Gong "Failed to update MAC, err: %d, status: 0x%x\n", 206*17fcb3dcSFan Gong err, mac_info.msg_head.status); 207*17fcb3dcSFan Gong return -EIO; 208*17fcb3dcSFan Gong } 209*17fcb3dcSFan Gong return 0; 210*17fcb3dcSFan Gong } 211*17fcb3dcSFan Gong 212*17fcb3dcSFan Gong int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev) 213*17fcb3dcSFan Gong { 214*17fcb3dcSFan Gong struct l2nic_cmd_force_pkt_drop pkt_drop = {}; 215*17fcb3dcSFan Gong struct mgmt_msg_params msg_params = {}; 216*17fcb3dcSFan Gong int err; 217*17fcb3dcSFan Gong 218*17fcb3dcSFan Gong pkt_drop.port = hinic3_physical_port_id(hwdev); 219*17fcb3dcSFan Gong 220*17fcb3dcSFan Gong mgmt_msg_params_init_default(&msg_params, &pkt_drop, sizeof(pkt_drop)); 221*17fcb3dcSFan Gong 222*17fcb3dcSFan Gong err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 223*17fcb3dcSFan Gong L2NIC_CMD_FORCE_PKT_DROP, &msg_params); 224*17fcb3dcSFan Gong if ((pkt_drop.msg_head.status != MGMT_STATUS_CMD_UNSUPPORTED && 225*17fcb3dcSFan Gong pkt_drop.msg_head.status) || err) { 226*17fcb3dcSFan Gong dev_err(hwdev->dev, 227*17fcb3dcSFan Gong "Failed to set force tx packets drop, err: %d, status: 0x%x\n", 228*17fcb3dcSFan Gong err, pkt_drop.msg_head.status); 229*17fcb3dcSFan Gong return -EFAULT; 230*17fcb3dcSFan Gong } 231*17fcb3dcSFan Gong 232*17fcb3dcSFan Gong return pkt_drop.msg_head.status; 233*17fcb3dcSFan Gong } 234