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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c
Extension
.c
Size
25357 bytes
Lines
929
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

if (left <= MBOX_SEG_LEN) {
			header &= cpu_to_le64(~MBOX_MSG_HEADER_SEG_LEN_MASK);
			header |=
				cpu_to_le64(MBOX_MSG_HEADER_SET(left, SEG_LEN) |
					    MBOX_MSG_HEADER_SET(1, LAST));
			seg_len = left;
		}

		err = send_mbox_seg(mbox, header, dst_func, msg_seg,
				    seg_len, msg_info);
		if (err) {
			dev_err(hwdev->dev, "Failed to send mbox seg, seq_id=0x%llx\n",
				MBOX_MSG_HEADER_GET(header, SEQID));
			goto err_send;
		}

		left -= MBOX_SEG_LEN;
		msg_seg += MBOX_SEG_LEN;
		seq_id++;
		header &= cpu_to_le64(~MBOX_MSG_HEADER_SEG_LEN_MASK);
		header |= cpu_to_le64(MBOX_MSG_HEADER_SET(seq_id, SEQID));
	}

err_send:
	mutex_unlock(&mbox->mbox_seg_send_lock);

	return err;
}

static void set_mbox_to_func_event(struct hinic3_mbox *mbox,
				   enum mbox_event_state event_flag)
{
	spin_lock(&mbox->mbox_lock);
	mbox->event_flag = event_flag;
	spin_unlock(&mbox->mbox_lock);
}

static enum hinic3_wait_return check_mbox_msg_finish(void *priv_data)
{
	struct hinic3_mbox *mbox = priv_data;

	if (!mbox->hwdev->chip_present_flag)
		return HINIC3_WAIT_PROCESS_ERR;

	return (mbox->event_flag == MBOX_EVENT_SUCCESS) ?
		HINIC3_WAIT_PROCESS_CPL : HINIC3_WAIT_PROCESS_WAITING;
}

static int wait_mbox_msg_completion(struct hinic3_mbox *mbox,
				    u32 timeout)
{
	u32 wait_time;
	int err;

	wait_time = (timeout != 0) ? timeout : MBOX_COMP_POLLING_TIMEOUT_MS;
	err = hinic3_wait_for_timeout(mbox, check_mbox_msg_finish,
				      wait_time, USEC_PER_MSEC);
	if (err) {
		set_mbox_to_func_event(mbox, MBOX_EVENT_TIMEOUT);
		return err;
	}
	set_mbox_to_func_event(mbox, MBOX_EVENT_END);

	return 0;
}

int hinic3_send_mbox_to_mgmt(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd,
			     const struct mgmt_msg_params *msg_params)
{
	struct hinic3_mbox *mbox = hwdev->mbox;
	struct mbox_msg_info msg_info = {};
	struct hinic3_msg_desc *msg_desc;
	u32 msg_len;
	int err;

	if (!hwdev->chip_present_flag)
		return -EPERM;

	/* expect response message */
	msg_desc = get_mbox_msg_desc(mbox, MBOX_MSG_RESP, MBOX_MGMT_FUNC_ID);
	mutex_lock(&mbox->mbox_send_lock);
	msg_info.msg_id = (mbox->send_msg_id + 1) & 0xF;
	mbox->send_msg_id = msg_info.msg_id;
	set_mbox_to_func_event(mbox, MBOX_EVENT_START);

	err = send_mbox_msg(mbox, mod, cmd, msg_params->buf_in,
			    msg_params->in_size, MBOX_MGMT_FUNC_ID,
			    MBOX_MSG_SEND, MBOX_MSG_ACK, &msg_info);
	if (err) {
		dev_err(hwdev->dev, "Send mailbox mod %u, cmd %u failed, msg_id: %u, err: %d\n",

Annotation

Implementation Notes