drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
Extension
.c
Size
20291 bytes
Lines
741
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.

#include <linux/if_vlan.h>

#include "hinic3_hwdev.h"
#include "hinic3_hwif.h"
#include "hinic3_mbox.h"
#include "hinic3_nic_cfg.h"
#include "hinic3_nic_dev.h"
#include "hinic3_nic_io.h"

#define MGMT_MSG_CMD_OP_ADD  1
#define MGMT_MSG_CMD_OP_DEL  0

static int hinic3_feature_nego(struct hinic3_hwdev *hwdev, u8 opcode,
			       u64 *s_feature, u16 size)
{
	struct l2nic_cmd_feature_nego feature_nego = {};
	struct mgmt_msg_params msg_params = {};
	int err;

	feature_nego.func_id = hinic3_global_func_id(hwdev);
	feature_nego.opcode = opcode;
	if (opcode == MGMT_MSG_CMD_OP_SET)
		memcpy(feature_nego.s_feature, s_feature,
		       array_size(size, sizeof(u64)));

	mgmt_msg_params_init_default(&msg_params, &feature_nego,
				     sizeof(feature_nego));

	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
				       L2NIC_CMD_FEATURE_NEGO, &msg_params);
	if (err || feature_nego.msg_head.status) {
		dev_err(hwdev->dev, "Failed to negotiate nic feature, err:%d, status: 0x%x\n",
			err, feature_nego.msg_head.status);
		return -EIO;
	}

	if (opcode == MGMT_MSG_CMD_OP_GET)
		memcpy(s_feature, feature_nego.s_feature,
		       array_size(size, sizeof(u64)));

	return 0;
}

int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev)
{
	return hinic3_feature_nego(nic_dev->hwdev, MGMT_MSG_CMD_OP_GET,
				   &nic_dev->nic_io->feature_cap, 1);
}

int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev)
{
	return hinic3_feature_nego(nic_dev->hwdev, MGMT_MSG_CMD_OP_SET,
				   &nic_dev->nic_io->feature_cap, 1);
}

bool hinic3_test_support(struct hinic3_nic_dev *nic_dev,
			 enum hinic3_nic_feature_cap feature_bits)
{
	return (nic_dev->nic_io->feature_cap & feature_bits) == feature_bits;
}

static int hinic3_set_rx_lro(struct hinic3_hwdev *hwdev, u8 ipv4_en, u8 ipv6_en,
			     u8 lro_max_pkt_len)
{
	struct l2nic_cmd_lro_config lro_cfg = {};
	struct mgmt_msg_params msg_params = {};
	int err;

	lro_cfg.func_id = hinic3_global_func_id(hwdev);
	lro_cfg.opcode = MGMT_MSG_CMD_OP_SET;
	lro_cfg.lro_ipv4_en = ipv4_en;
	lro_cfg.lro_ipv6_en = ipv6_en;
	lro_cfg.lro_max_pkt_len = lro_max_pkt_len;

	mgmt_msg_params_init_default(&msg_params, &lro_cfg,
				     sizeof(lro_cfg));

	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
				       L2NIC_CMD_CFG_RX_LRO,
				       &msg_params);

	if (err || lro_cfg.msg_head.status) {
		dev_err(hwdev->dev, "Failed to set lro offload, err: %d, status: 0x%x\n",
			err, lro_cfg.msg_head.status);
		return -EFAULT;
	}

Annotation

Implementation Notes