drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
Extension
.c
Size
11150 bytes
Lines
389
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 (status) {
			dev_err(&hdev->pdev->dev,
				"VF failed(=%d) to send mbx message to PF\n",
				status);
			mutex_unlock(&hdev->mbx_resp.mbx_mutex);
			return status;
		}

		status = hclgevf_get_mbx_resp(hdev, send_msg->code,
					      send_msg->subcode, resp_data,
					      resp_len);
		mutex_unlock(&hdev->mbx_resp.mbx_mutex);
	} else {
		/* asynchronous send */
		status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
		if (status) {
			dev_err(&hdev->pdev->dev,
				"VF failed(=%d) to send mbx message to PF\n",
				status);
			return status;
		}
	}

	return status;
}

static bool hclgevf_cmd_crq_empty(struct hclgevf_hw *hw)
{
	u32 tail = hclgevf_read_dev(hw, HCLGE_COMM_NIC_CRQ_TAIL_REG);

	return tail == (u32)hw->hw.cmq.crq.next_to_use;
}

static void hclgevf_handle_mbx_response(struct hclgevf_dev *hdev,
					struct hclge_mbx_pf_to_vf_cmd *req)
{
	u16 vf_mbx_msg_subcode = le16_to_cpu(req->msg.vf_mbx_msg_subcode);
	u16 vf_mbx_msg_code = le16_to_cpu(req->msg.vf_mbx_msg_code);
	struct hclgevf_mbx_resp_status *resp = &hdev->mbx_resp;
	u16 resp_status = le16_to_cpu(req->msg.resp_status);
	u16 match_id = le16_to_cpu(req->match_id);

	if (resp->received_resp)
		dev_warn(&hdev->pdev->dev,
			"VF mbx resp flag not clear(%u)\n",
			 vf_mbx_msg_code);

	resp->origin_mbx_msg = (vf_mbx_msg_code << 16);
	resp->origin_mbx_msg |= vf_mbx_msg_subcode;
	resp->resp_status = hclgevf_resp_to_errno(resp_status);
	memcpy(resp->additional_info, req->msg.resp_data,
	       HCLGE_MBX_MAX_RESP_DATA_SIZE * sizeof(u8));

	/* ensure additional_info will be seen before setting received_resp */
	smp_wmb();

	if (match_id) {
		/* If match_id is not zero, it means PF support match_id.
		 * if the match_id is right, VF get the right response, or
		 * ignore the response. and driver will clear hdev->mbx_resp
		 * when send next message which need response.
		 */
		if (match_id == resp->match_id)
			resp->received_resp = true;
	} else {
		resp->received_resp = true;
	}
}

static void hclgevf_handle_mbx_msg(struct hclgevf_dev *hdev,
				   struct hclge_mbx_pf_to_vf_cmd *req)
{
	/* we will drop the async msg if we find ARQ as full
	 * and continue with next message
	 */
	if (atomic_read(&hdev->arq.count) >=
	    HCLGE_MBX_MAX_ARQ_MSG_NUM) {
		dev_warn(&hdev->pdev->dev,
			 "Async Q full, dropping msg(%u)\n",
			 le16_to_cpu(req->msg.code));
		return;
	}

	/* tail the async message in arq */
	memcpy(hdev->arq.msg_q[hdev->arq.tail], &req->msg,
	       HCLGE_MBX_MAX_ARQ_MSG_SIZE * sizeof(u16));
	hclge_mbx_tail_ptr_move_arq(hdev->arq);
	atomic_inc(&hdev->arq.count);

	hclgevf_mbx_task_schedule(hdev);

Annotation

Implementation Notes