brintos

brintos / linux-shallow public Read only

0
0
Text · 42.0 KiB · 3f9c31d Raw
1516 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Huawei HiNIC PCI Express Linux driver3 * Copyright(c) 2017 Huawei Technologies Co., Ltd4 */5#include <linux/pci.h>6#include <linux/delay.h>7#include <linux/types.h>8#include <linux/completion.h>9#include <linux/semaphore.h>10#include <linux/spinlock.h>11#include <linux/workqueue.h>12 13#include "hinic_hw_if.h"14#include "hinic_hw_mgmt.h"15#include "hinic_hw_csr.h"16#include "hinic_hw_dev.h"17#include "hinic_hw_mbox.h"18 19#define HINIC_MBOX_INT_DST_FUNC_SHIFT				020#define HINIC_MBOX_INT_DST_AEQN_SHIFT				1021#define HINIC_MBOX_INT_SRC_RESP_AEQN_SHIFT			1222#define HINIC_MBOX_INT_STAT_DMA_SHIFT				1423/* The size of data to be sended (unit of 4 bytes) */24#define HINIC_MBOX_INT_TX_SIZE_SHIFT				2025/* SO_RO(strong order, relax order) */26#define HINIC_MBOX_INT_STAT_DMA_SO_RO_SHIFT			2527#define HINIC_MBOX_INT_WB_EN_SHIFT				2828 29#define HINIC_MBOX_INT_DST_FUNC_MASK				0x3FF30#define HINIC_MBOX_INT_DST_AEQN_MASK				0x331#define HINIC_MBOX_INT_SRC_RESP_AEQN_MASK			0x332#define HINIC_MBOX_INT_STAT_DMA_MASK				0x3F33#define HINIC_MBOX_INT_TX_SIZE_MASK				0x1F34#define HINIC_MBOX_INT_STAT_DMA_SO_RO_MASK			0x335#define HINIC_MBOX_INT_WB_EN_MASK				0x136 37#define HINIC_MBOX_INT_SET(val, field)	\38			(((val) & HINIC_MBOX_INT_##field##_MASK) << \39			HINIC_MBOX_INT_##field##_SHIFT)40 41enum hinic_mbox_tx_status {42	TX_NOT_DONE = 1,43};44 45#define HINIC_MBOX_CTRL_TRIGGER_AEQE_SHIFT			046 47/* specifies the issue request for the message data.48 * 0 - Tx request is done;49 * 1 - Tx request is in process.50 */51#define HINIC_MBOX_CTRL_TX_STATUS_SHIFT				152 53#define HINIC_MBOX_CTRL_TRIGGER_AEQE_MASK			0x154#define HINIC_MBOX_CTRL_TX_STATUS_MASK				0x155 56#define HINIC_MBOX_CTRL_SET(val, field)	\57			(((val) & HINIC_MBOX_CTRL_##field##_MASK) << \58			HINIC_MBOX_CTRL_##field##_SHIFT)59 60#define HINIC_MBOX_HEADER_MSG_LEN_SHIFT				061#define HINIC_MBOX_HEADER_MODULE_SHIFT				1162#define HINIC_MBOX_HEADER_SEG_LEN_SHIFT				1663#define HINIC_MBOX_HEADER_NO_ACK_SHIFT				2264#define HINIC_MBOX_HEADER_SEQID_SHIFT				2465#define HINIC_MBOX_HEADER_LAST_SHIFT				3066 67/* specifies the mailbox message direction68 * 0 - send69 * 1 - receive70 */71#define HINIC_MBOX_HEADER_DIRECTION_SHIFT			3172#define HINIC_MBOX_HEADER_CMD_SHIFT				3273#define HINIC_MBOX_HEADER_MSG_ID_SHIFT				4074#define HINIC_MBOX_HEADER_STATUS_SHIFT				4875#define HINIC_MBOX_HEADER_SRC_GLB_FUNC_IDX_SHIFT		5476 77#define HINIC_MBOX_HEADER_MSG_LEN_MASK				0x7FF78#define HINIC_MBOX_HEADER_MODULE_MASK				0x1F79#define HINIC_MBOX_HEADER_SEG_LEN_MASK				0x3F80#define HINIC_MBOX_HEADER_NO_ACK_MASK				0x181#define HINIC_MBOX_HEADER_SEQID_MASK				0x3F82#define HINIC_MBOX_HEADER_LAST_MASK				0x183#define HINIC_MBOX_HEADER_DIRECTION_MASK			0x184#define HINIC_MBOX_HEADER_CMD_MASK				0xFF85#define HINIC_MBOX_HEADER_MSG_ID_MASK				0xFF86#define HINIC_MBOX_HEADER_STATUS_MASK				0x3F87#define HINIC_MBOX_HEADER_SRC_GLB_FUNC_IDX_MASK			0x3FF88 89#define HINIC_MBOX_HEADER_GET(val, field)	\90			(((val) >> HINIC_MBOX_HEADER_##field##_SHIFT) & \91			HINIC_MBOX_HEADER_##field##_MASK)92#define HINIC_MBOX_HEADER_SET(val, field)	\93			((u64)((val) & HINIC_MBOX_HEADER_##field##_MASK) << \94			HINIC_MBOX_HEADER_##field##_SHIFT)95 96#define MBOX_SEGLEN_MASK			\97		HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEG_LEN_MASK, SEG_LEN)98 99#define HINIC_MBOX_SEG_LEN			48100#define HINIC_MBOX_COMP_TIME			8000U101#define MBOX_MSG_POLLING_TIMEOUT		8000102 103#define HINIC_MBOX_DATA_SIZE			2040104 105#define MBOX_MAX_BUF_SZ				2048UL106#define MBOX_HEADER_SZ				8107 108#define MBOX_INFO_SZ				4109 110/* MBOX size is 64B, 8B for mbox_header, 4B reserved */111#define MBOX_SEG_LEN				48112#define MBOX_SEG_LEN_ALIGN			4113#define MBOX_WB_STATUS_LEN			16UL114 115/* mbox write back status is 16B, only first 4B is used */116#define MBOX_WB_STATUS_ERRCODE_MASK		0xFFFF117#define MBOX_WB_STATUS_MASK			0xFF118#define MBOX_WB_ERROR_CODE_MASK			0xFF00119#define MBOX_WB_STATUS_FINISHED_SUCCESS		0xFF120#define MBOX_WB_STATUS_NOT_FINISHED		0x00121 122#define MBOX_STATUS_FINISHED(wb)	\123	(((wb) & MBOX_WB_STATUS_MASK) != MBOX_WB_STATUS_NOT_FINISHED)124#define MBOX_STATUS_SUCCESS(wb)		\125	(((wb) & MBOX_WB_STATUS_MASK) == MBOX_WB_STATUS_FINISHED_SUCCESS)126#define MBOX_STATUS_ERRCODE(wb)		\127	((wb) & MBOX_WB_ERROR_CODE_MASK)128 129#define SEQ_ID_START_VAL			0130#define SEQ_ID_MAX_VAL				42131 132#define NO_DMA_ATTRIBUTE_VAL			0133 134#define HINIC_MBOX_RSP_AEQN			2135#define HINIC_MBOX_RECV_AEQN			0136 137#define MBOX_MSG_NO_DATA_LEN			1138 139#define MBOX_BODY_FROM_HDR(header)	((u8 *)(header) + MBOX_HEADER_SZ)140#define MBOX_AREA(hwif)			\141	((hwif)->cfg_regs_bar + HINIC_FUNC_CSR_MAILBOX_DATA_OFF)142 143#define IS_PF_OR_PPF_SRC(src_func_idx)	((src_func_idx) < HINIC_MAX_PF_FUNCS)144 145#define MBOX_MSG_ID_MASK		0xFF146#define MBOX_MSG_ID(func_to_func)	((func_to_func)->send_msg_id)147#define MBOX_MSG_ID_INC(func_to_func_mbox) (MBOX_MSG_ID(func_to_func_mbox) = \148			(MBOX_MSG_ID(func_to_func_mbox) + 1) & MBOX_MSG_ID_MASK)149 150#define FUNC_ID_OFF_SET_8B		8151 152/* max message counter wait to process for one function */153#define HINIC_MAX_MSG_CNT_TO_PROCESS	10154 155#define HINIC_QUEUE_MIN_DEPTH		6156#define HINIC_QUEUE_MAX_DEPTH		12157#define HINIC_MAX_RX_BUFFER_SIZE		15158 159enum hinic_hwif_direction_type {160	HINIC_HWIF_DIRECT_SEND	= 0,161	HINIC_HWIF_RESPONSE	= 1,162};163 164enum mbox_send_mod {165	MBOX_SEND_MSG_INT,166};167 168enum mbox_seg_type {169	NOT_LAST_SEG,170	LAST_SEG,171};172 173enum mbox_ordering_type {174	STRONG_ORDER,175};176 177enum mbox_write_back_type {178	WRITE_BACK = 1,179};180 181enum mbox_aeq_trig_type {182	NOT_TRIGGER,183	TRIGGER,184};185 186static bool check_func_id(struct hinic_hwdev *hwdev, u16 src_func_idx,187			  const void *buf_in, u16 in_size, u16 offset)188{189	u16 func_idx;190 191	if (in_size < offset + sizeof(func_idx)) {192		dev_warn(&hwdev->hwif->pdev->dev,193			 "Receive mailbox msg len: %d less than %d Bytes is invalid\n",194			 in_size, offset);195		return false;196	}197 198	func_idx = *((u16 *)((u8 *)buf_in + offset));199 200	if (src_func_idx != func_idx) {201		dev_warn(&hwdev->hwif->pdev->dev,202			 "Receive mailbox function id: 0x%x not equal to msg function id: 0x%x\n",203			 src_func_idx, func_idx);204		return false;205	}206 207	return true;208}209 210bool hinic_mbox_check_func_id_8B(struct hinic_hwdev *hwdev, u16 func_idx,211				 void *buf_in, u16 in_size)212{213	return check_func_id(hwdev, func_idx, buf_in, in_size,214			     FUNC_ID_OFF_SET_8B);215}216 217/**218 * hinic_register_pf_mbox_cb - register mbox callback for pf219 * @hwdev: the pointer to hw device220 * @mod:	specific mod that the callback will handle221 * @callback:	callback function222 * Return: 0 - success, negative - failure223 */224int hinic_register_pf_mbox_cb(struct hinic_hwdev *hwdev,225			      enum hinic_mod_type mod,226			      hinic_pf_mbox_cb callback)227{228	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;229 230	if (mod >= HINIC_MOD_MAX)231		return -EFAULT;232 233	func_to_func->pf_mbox_cb[mod] = callback;234 235	set_bit(HINIC_PF_MBOX_CB_REG, &func_to_func->pf_mbox_cb_state[mod]);236 237	return 0;238}239 240/**241 * hinic_register_vf_mbox_cb - register mbox callback for vf242 * @hwdev: the pointer to hw device243 * @mod:	specific mod that the callback will handle244 * @callback:	callback function245 * Return: 0 - success, negative - failure246 */247int hinic_register_vf_mbox_cb(struct hinic_hwdev *hwdev,248			      enum hinic_mod_type mod,249			      hinic_vf_mbox_cb callback)250{251	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;252 253	if (mod >= HINIC_MOD_MAX)254		return -EFAULT;255 256	func_to_func->vf_mbox_cb[mod] = callback;257 258	set_bit(HINIC_VF_MBOX_CB_REG, &func_to_func->vf_mbox_cb_state[mod]);259 260	return 0;261}262 263/**264 * hinic_unregister_pf_mbox_cb - unregister the mbox callback for pf265 * @hwdev:	the pointer to hw device266 * @mod:	specific mod that the callback will handle267 */268void hinic_unregister_pf_mbox_cb(struct hinic_hwdev *hwdev,269				 enum hinic_mod_type mod)270{271	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;272 273	clear_bit(HINIC_PF_MBOX_CB_REG, &func_to_func->pf_mbox_cb_state[mod]);274 275	while (test_bit(HINIC_PF_MBOX_CB_RUNNING,276			&func_to_func->pf_mbox_cb_state[mod]))277		usleep_range(900, 1000);278 279	func_to_func->pf_mbox_cb[mod] = NULL;280}281 282/**283 * hinic_unregister_vf_mbox_cb - unregister the mbox callback for vf284 * @hwdev:	the pointer to hw device285 * @mod:	specific mod that the callback will handle286 */287void hinic_unregister_vf_mbox_cb(struct hinic_hwdev *hwdev,288				 enum hinic_mod_type mod)289{290	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;291 292	clear_bit(HINIC_VF_MBOX_CB_REG, &func_to_func->vf_mbox_cb_state[mod]);293 294	while (test_bit(HINIC_VF_MBOX_CB_RUNNING,295			&func_to_func->vf_mbox_cb_state[mod]))296		usleep_range(900, 1000);297 298	func_to_func->vf_mbox_cb[mod] = NULL;299}300 301static int recv_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,302				struct hinic_recv_mbox *recv_mbox,303				void *buf_out, u16 *out_size)304{305	hinic_vf_mbox_cb cb;306	int ret = 0;307 308	if (recv_mbox->mod >= HINIC_MOD_MAX) {309		dev_err(&func_to_func->hwif->pdev->dev, "Receive illegal mbox message, mod = %d\n",310			recv_mbox->mod);311		return -EINVAL;312	}313 314	set_bit(HINIC_VF_MBOX_CB_RUNNING,315		&func_to_func->vf_mbox_cb_state[recv_mbox->mod]);316 317	cb = func_to_func->vf_mbox_cb[recv_mbox->mod];318	if (cb && test_bit(HINIC_VF_MBOX_CB_REG,319			   &func_to_func->vf_mbox_cb_state[recv_mbox->mod])) {320		cb(func_to_func->hwdev, recv_mbox->cmd, recv_mbox->mbox,321		   recv_mbox->mbox_len, buf_out, out_size);322	} else {323		dev_err(&func_to_func->hwif->pdev->dev, "VF mbox cb is not registered\n");324		ret = -EINVAL;325	}326 327	clear_bit(HINIC_VF_MBOX_CB_RUNNING,328		  &func_to_func->vf_mbox_cb_state[recv_mbox->mod]);329 330	return ret;331}332 333static int334recv_pf_from_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,335			     struct hinic_recv_mbox *recv_mbox,336			     u16 src_func_idx, void *buf_out,337			     u16 *out_size)338{339	hinic_pf_mbox_cb cb;340	u16 vf_id = 0;341	int ret;342 343	if (recv_mbox->mod >= HINIC_MOD_MAX) {344		dev_err(&func_to_func->hwif->pdev->dev, "Receive illegal mbox message, mod = %d\n",345			recv_mbox->mod);346		return -EINVAL;347	}348 349	set_bit(HINIC_PF_MBOX_CB_RUNNING,350		&func_to_func->pf_mbox_cb_state[recv_mbox->mod]);351 352	cb = func_to_func->pf_mbox_cb[recv_mbox->mod];353	if (cb && test_bit(HINIC_PF_MBOX_CB_REG,354			   &func_to_func->pf_mbox_cb_state[recv_mbox->mod])) {355		vf_id = src_func_idx -356			hinic_glb_pf_vf_offset(func_to_func->hwif);357		ret = cb(func_to_func->hwdev, vf_id, recv_mbox->cmd,358			 recv_mbox->mbox, recv_mbox->mbox_len,359			 buf_out, out_size);360	} else {361		dev_err(&func_to_func->hwif->pdev->dev, "PF mbox mod(0x%x) cb is not registered\n",362			recv_mbox->mod);363		ret = -EINVAL;364	}365 366	clear_bit(HINIC_PF_MBOX_CB_RUNNING,367		  &func_to_func->pf_mbox_cb_state[recv_mbox->mod]);368 369	return ret;370}371 372static bool check_mbox_seq_id_and_seg_len(struct hinic_recv_mbox *recv_mbox,373					  u8 seq_id, u8 seg_len)374{375	if (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN)376		return false;377 378	if (seq_id == 0) {379		recv_mbox->seq_id = seq_id;380	} else {381		if (seq_id != recv_mbox->seq_id + 1)382			return false;383 384		recv_mbox->seq_id = seq_id;385	}386 387	return true;388}389 390static void resp_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,391			      struct hinic_recv_mbox *recv_mbox)392{393	spin_lock(&func_to_func->mbox_lock);394	if (recv_mbox->msg_info.msg_id == func_to_func->send_msg_id &&395	    func_to_func->event_flag == EVENT_START)396		complete(&recv_mbox->recv_done);397	else398		dev_err(&func_to_func->hwif->pdev->dev,399			"Mbox response timeout, current send msg id(0x%x), recv msg id(0x%x), status(0x%x)\n",400			func_to_func->send_msg_id, recv_mbox->msg_info.msg_id,401			recv_mbox->msg_info.status);402	spin_unlock(&func_to_func->mbox_lock);403}404 405static void recv_func_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,406				   struct hinic_recv_mbox *recv_mbox,407				   u16 src_func_idx);408 409static void recv_func_mbox_work_handler(struct work_struct *work)410{411	struct hinic_mbox_work *mbox_work =412			container_of(work, struct hinic_mbox_work, work);413	struct hinic_recv_mbox *recv_mbox;414 415	recv_func_mbox_handler(mbox_work->func_to_func, mbox_work->recv_mbox,416			       mbox_work->src_func_idx);417 418	recv_mbox =419		&mbox_work->func_to_func->mbox_send[mbox_work->src_func_idx];420 421	atomic_dec(&recv_mbox->msg_cnt);422 423	kfree(mbox_work);424}425 426static void recv_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,427			      void *header, struct hinic_recv_mbox *recv_mbox)428{429	void *mbox_body = MBOX_BODY_FROM_HDR(header);430	struct hinic_recv_mbox *rcv_mbox_temp = NULL;431	u64 mbox_header = *((u64 *)header);432	struct hinic_mbox_work *mbox_work;433	u8 seq_id, seg_len;434	u16 src_func_idx;435	int pos;436 437	seq_id = HINIC_MBOX_HEADER_GET(mbox_header, SEQID);438	seg_len = HINIC_MBOX_HEADER_GET(mbox_header, SEG_LEN);439	src_func_idx = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);440 441	if (!check_mbox_seq_id_and_seg_len(recv_mbox, seq_id, seg_len)) {442		dev_err(&func_to_func->hwif->pdev->dev,443			"Mailbox sequence and segment check fail, src func id: 0x%x, front id: 0x%x, current id: 0x%x, seg len: 0x%x\n",444			src_func_idx, recv_mbox->seq_id, seq_id, seg_len);445		recv_mbox->seq_id = SEQ_ID_MAX_VAL;446		return;447	}448 449	pos = seq_id * MBOX_SEG_LEN;450	memcpy((u8 *)recv_mbox->mbox + pos, mbox_body,451	       HINIC_MBOX_HEADER_GET(mbox_header, SEG_LEN));452 453	if (!HINIC_MBOX_HEADER_GET(mbox_header, LAST))454		return;455 456	recv_mbox->cmd = HINIC_MBOX_HEADER_GET(mbox_header, CMD);457	recv_mbox->mod = HINIC_MBOX_HEADER_GET(mbox_header, MODULE);458	recv_mbox->mbox_len = HINIC_MBOX_HEADER_GET(mbox_header, MSG_LEN);459	recv_mbox->ack_type = HINIC_MBOX_HEADER_GET(mbox_header, NO_ACK);460	recv_mbox->msg_info.msg_id = HINIC_MBOX_HEADER_GET(mbox_header, MSG_ID);461	recv_mbox->msg_info.status = HINIC_MBOX_HEADER_GET(mbox_header, STATUS);462	recv_mbox->seq_id = SEQ_ID_MAX_VAL;463 464	if (HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION) ==465	    HINIC_HWIF_RESPONSE) {466		resp_mbox_handler(func_to_func, recv_mbox);467		return;468	}469 470	if (atomic_read(&recv_mbox->msg_cnt) > HINIC_MAX_MSG_CNT_TO_PROCESS) {471		dev_warn(&func_to_func->hwif->pdev->dev,472			 "This function(%u) have %d message wait to process,can't add to work queue\n",473			 src_func_idx, atomic_read(&recv_mbox->msg_cnt));474		return;475	}476 477	rcv_mbox_temp = kmemdup(recv_mbox, sizeof(*rcv_mbox_temp), GFP_KERNEL);478	if (!rcv_mbox_temp)479		return;480 481	rcv_mbox_temp->mbox = kmemdup(recv_mbox->mbox, MBOX_MAX_BUF_SZ,482				      GFP_KERNEL);483	if (!rcv_mbox_temp->mbox)484		goto err_alloc_rcv_mbox_msg;485 486	rcv_mbox_temp->buf_out = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);487	if (!rcv_mbox_temp->buf_out)488		goto err_alloc_rcv_mbox_buf;489 490	mbox_work = kzalloc(sizeof(*mbox_work), GFP_KERNEL);491	if (!mbox_work)492		goto err_alloc_mbox_work;493 494	mbox_work->func_to_func = func_to_func;495	mbox_work->recv_mbox = rcv_mbox_temp;496	mbox_work->src_func_idx = src_func_idx;497 498	atomic_inc(&recv_mbox->msg_cnt);499	INIT_WORK(&mbox_work->work, recv_func_mbox_work_handler);500	queue_work(func_to_func->workq, &mbox_work->work);501 502	return;503 504err_alloc_mbox_work:505	kfree(rcv_mbox_temp->buf_out);506 507err_alloc_rcv_mbox_buf:508	kfree(rcv_mbox_temp->mbox);509 510err_alloc_rcv_mbox_msg:511	kfree(rcv_mbox_temp);512}513 514static int set_vf_mbox_random_id(struct hinic_hwdev *hwdev, u16 func_id)515{516	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;517	struct hinic_set_random_id rand_info = {0};518	u16 out_size = sizeof(rand_info);519	struct hinic_pfhwdev *pfhwdev;520	int ret;521 522	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);523 524	rand_info.version = HINIC_CMD_VER_FUNC_ID;525	rand_info.func_idx = func_id;526	rand_info.vf_in_pf = func_id - hinic_glb_pf_vf_offset(hwdev->hwif);527	rand_info.random_id = get_random_u32();528 529	func_to_func->vf_mbx_rand_id[func_id] = rand_info.random_id;530 531	ret = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,532				HINIC_MGMT_CMD_SET_VF_RANDOM_ID,533				&rand_info, sizeof(rand_info),534				&rand_info, &out_size, HINIC_MGMT_MSG_SYNC);535	if ((rand_info.status != HINIC_MGMT_CMD_UNSUPPORTED &&536	     rand_info.status) || !out_size || ret) {537		dev_err(&hwdev->hwif->pdev->dev, "Set VF random id failed, err: %d, status: 0x%x, out size: 0x%x\n",538			ret, rand_info.status, out_size);539		return -EIO;540	}541 542	if (rand_info.status == HINIC_MGMT_CMD_UNSUPPORTED)543		return rand_info.status;544 545	func_to_func->vf_mbx_old_rand_id[func_id] =546				func_to_func->vf_mbx_rand_id[func_id];547 548	return 0;549}550 551static void update_random_id_work_handler(struct work_struct *work)552{553	struct hinic_mbox_work *mbox_work =554			container_of(work, struct hinic_mbox_work, work);555	struct hinic_mbox_func_to_func *func_to_func;556	u16 src = mbox_work->src_func_idx;557 558	func_to_func = mbox_work->func_to_func;559 560	if (set_vf_mbox_random_id(func_to_func->hwdev, src))561		dev_warn(&func_to_func->hwdev->hwif->pdev->dev, "Update VF id: 0x%x random id failed\n",562			 mbox_work->src_func_idx);563 564	kfree(mbox_work);565}566 567static bool check_vf_mbox_random_id(struct hinic_mbox_func_to_func *func_to_func,568				    u8 *header)569{570	struct hinic_hwdev *hwdev = func_to_func->hwdev;571	struct hinic_mbox_work *mbox_work = NULL;572	u64 mbox_header = *((u64 *)header);573	u16 offset, src;574	u32 random_id;575	int vf_in_pf;576 577	src = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);578 579	if (IS_PF_OR_PPF_SRC(src) || !func_to_func->support_vf_random)580		return true;581 582	if (!HINIC_IS_PPF(hwdev->hwif)) {583		offset = hinic_glb_pf_vf_offset(hwdev->hwif);584		vf_in_pf = src - offset;585 586		if (vf_in_pf < 1 || vf_in_pf > hwdev->nic_cap.max_vf) {587			dev_warn(&hwdev->hwif->pdev->dev,588				 "Receive vf id(0x%x) is invalid, vf id should be from 0x%x to 0x%x\n",589				 src, offset + 1,590				 hwdev->nic_cap.max_vf + offset);591			return false;592		}593	}594 595	random_id = be32_to_cpu(*(u32 *)(header + MBOX_SEG_LEN +596					 MBOX_HEADER_SZ));597 598	if (random_id == func_to_func->vf_mbx_rand_id[src] ||599	    random_id == func_to_func->vf_mbx_old_rand_id[src])600		return true;601 602	dev_warn(&hwdev->hwif->pdev->dev,603		 "The mailbox random id(0x%x) of func_id(0x%x) doesn't match with pf reservation(0x%x)\n",604		 random_id, src, func_to_func->vf_mbx_rand_id[src]);605 606	mbox_work = kzalloc(sizeof(*mbox_work), GFP_KERNEL);607	if (!mbox_work)608		return false;609 610	mbox_work->func_to_func = func_to_func;611	mbox_work->src_func_idx = src;612 613	INIT_WORK(&mbox_work->work, update_random_id_work_handler);614	queue_work(func_to_func->workq, &mbox_work->work);615 616	return false;617}618 619static void hinic_mbox_func_aeqe_handler(void *handle, void *header, u8 size)620{621	struct hinic_mbox_func_to_func *func_to_func;622	u64 mbox_header = *((u64 *)header);623	struct hinic_recv_mbox *recv_mbox;624	u64 src, dir;625 626	func_to_func = ((struct hinic_hwdev *)handle)->func_to_func;627 628	dir = HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION);629	src = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);630 631	if (src >= HINIC_MAX_FUNCTIONS) {632		dev_err(&func_to_func->hwif->pdev->dev,633			"Mailbox source function id:%u is invalid\n", (u32)src);634		return;635	}636 637	if (!check_vf_mbox_random_id(func_to_func, header))638		return;639 640	recv_mbox = (dir == HINIC_HWIF_DIRECT_SEND) ?641		    &func_to_func->mbox_send[src] :642		    &func_to_func->mbox_resp[src];643 644	recv_mbox_handler(func_to_func, (u64 *)header, recv_mbox);645}646 647static void hinic_mbox_self_aeqe_handler(void *handle, void *header, u8 size)648{649	struct hinic_mbox_func_to_func *func_to_func;650	struct hinic_send_mbox *send_mbox;651 652	func_to_func = ((struct hinic_hwdev *)handle)->func_to_func;653	send_mbox = &func_to_func->send_mbox;654 655	complete(&send_mbox->send_done);656}657 658static void clear_mbox_status(struct hinic_send_mbox *mbox)659{660	*mbox->wb_status = 0;661 662	/* clear mailbox write back status */663	wmb();664}665 666static void mbox_copy_header(struct hinic_hwdev *hwdev,667			     struct hinic_send_mbox *mbox, u64 *header)668{669	u32 i, idx_max = MBOX_HEADER_SZ / sizeof(u32);670	u32 *data = (u32 *)header;671 672	for (i = 0; i < idx_max; i++)673		__raw_writel(*(data + i), mbox->data + i * sizeof(u32));674}675 676static void mbox_copy_send_data(struct hinic_hwdev *hwdev,677				struct hinic_send_mbox *mbox, void *seg,678				u16 seg_len)679{680	u8 mbox_max_buf[MBOX_SEG_LEN] = {0};681	u32 data_len, chk_sz = sizeof(u32);682	u32 *data = seg;683	u32 i, idx_max;684 685	/* The mbox message should be aligned in 4 bytes. */686	if (seg_len % chk_sz) {687		memcpy(mbox_max_buf, seg, seg_len);688		data = (u32 *)mbox_max_buf;689	}690 691	data_len = seg_len;692	idx_max = ALIGN(data_len, chk_sz) / chk_sz;693 694	for (i = 0; i < idx_max; i++)695		__raw_writel(*(data + i),696			     mbox->data + MBOX_HEADER_SZ + i * sizeof(u32));697}698 699static void write_mbox_msg_attr(struct hinic_mbox_func_to_func *func_to_func,700				u16 dst_func, u16 dst_aeqn, u16 seg_len,701				int poll)702{703	u16 rsp_aeq = (dst_aeqn == 0) ? 0 : HINIC_MBOX_RSP_AEQN;704	u32 mbox_int, mbox_ctrl;705 706	mbox_int = HINIC_MBOX_INT_SET(dst_func, DST_FUNC) |707		   HINIC_MBOX_INT_SET(dst_aeqn, DST_AEQN) |708		   HINIC_MBOX_INT_SET(rsp_aeq, SRC_RESP_AEQN) |709		   HINIC_MBOX_INT_SET(NO_DMA_ATTRIBUTE_VAL, STAT_DMA) |710		   HINIC_MBOX_INT_SET(ALIGN(MBOX_SEG_LEN + MBOX_HEADER_SZ +711				      MBOX_INFO_SZ, MBOX_SEG_LEN_ALIGN) >> 2,712				      TX_SIZE) |713		   HINIC_MBOX_INT_SET(STRONG_ORDER, STAT_DMA_SO_RO) |714		   HINIC_MBOX_INT_SET(WRITE_BACK, WB_EN);715 716	hinic_hwif_write_reg(func_to_func->hwif,717			     HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF, mbox_int);718 719	wmb(); /* writing the mbox int attributes */720	mbox_ctrl = HINIC_MBOX_CTRL_SET(TX_NOT_DONE, TX_STATUS);721 722	if (poll)723		mbox_ctrl |= HINIC_MBOX_CTRL_SET(NOT_TRIGGER, TRIGGER_AEQE);724	else725		mbox_ctrl |= HINIC_MBOX_CTRL_SET(TRIGGER, TRIGGER_AEQE);726 727	hinic_hwif_write_reg(func_to_func->hwif,728			     HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF, mbox_ctrl);729}730 731static void dump_mox_reg(struct hinic_hwdev *hwdev)732{733	u32 val;734 735	val = hinic_hwif_read_reg(hwdev->hwif,736				  HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF);737	dev_err(&hwdev->hwif->pdev->dev, "Mailbox control reg: 0x%x\n", val);738 739	val = hinic_hwif_read_reg(hwdev->hwif,740				  HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF);741	dev_err(&hwdev->hwif->pdev->dev, "Mailbox interrupt offset: 0x%x\n",742		val);743}744 745static u16 get_mbox_status(struct hinic_send_mbox *mbox)746{747	/* write back is 16B, but only use first 4B */748	u64 wb_val = be64_to_cpu(*mbox->wb_status);749 750	rmb(); /* verify reading before check */751 752	return (u16)(wb_val & MBOX_WB_STATUS_ERRCODE_MASK);753}754 755static int756wait_for_mbox_seg_completion(struct hinic_mbox_func_to_func *func_to_func,757			     int poll, u16 *wb_status)758{759	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;760	struct hinic_hwdev *hwdev = func_to_func->hwdev;761	struct completion *done = &send_mbox->send_done;762	u32 cnt = 0;763	unsigned long jif;764 765	if (poll) {766		while (cnt < MBOX_MSG_POLLING_TIMEOUT) {767			*wb_status = get_mbox_status(send_mbox);768			if (MBOX_STATUS_FINISHED(*wb_status))769				break;770 771			usleep_range(900, 1000);772			cnt++;773		}774 775		if (cnt == MBOX_MSG_POLLING_TIMEOUT) {776			dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment timeout, wb status: 0x%x\n",777				*wb_status);778			dump_mox_reg(hwdev);779			return -ETIMEDOUT;780		}781	} else {782		jif = msecs_to_jiffies(HINIC_MBOX_COMP_TIME);783		if (!wait_for_completion_timeout(done, jif)) {784			dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment timeout\n");785			dump_mox_reg(hwdev);786			hinic_dump_aeq_info(hwdev);787			return -ETIMEDOUT;788		}789 790		*wb_status = get_mbox_status(send_mbox);791	}792 793	return 0;794}795 796static int send_mbox_seg(struct hinic_mbox_func_to_func *func_to_func,797			 u64 header, u16 dst_func, void *seg, u16 seg_len,798			 int poll, void *msg_info)799{800	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;801	u16 seq_dir = HINIC_MBOX_HEADER_GET(header, DIRECTION);802	struct hinic_hwdev *hwdev = func_to_func->hwdev;803	struct completion *done = &send_mbox->send_done;804	u8 num_aeqs = hwdev->hwif->attr.num_aeqs;805	u16 dst_aeqn, wb_status = 0, errcode;806 807	if (num_aeqs >= 4)808		dst_aeqn = (seq_dir == HINIC_HWIF_DIRECT_SEND) ?809			   HINIC_MBOX_RECV_AEQN : HINIC_MBOX_RSP_AEQN;810	else811		dst_aeqn = 0;812 813	if (!poll)814		init_completion(done);815 816	clear_mbox_status(send_mbox);817 818	mbox_copy_header(hwdev, send_mbox, &header);819 820	mbox_copy_send_data(hwdev, send_mbox, seg, seg_len);821 822	write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_len, poll);823 824	wmb(); /* writing the mbox msg attributes */825 826	if (wait_for_mbox_seg_completion(func_to_func, poll, &wb_status))827		return -ETIMEDOUT;828 829	if (!MBOX_STATUS_SUCCESS(wb_status)) {830		dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment to function %d error, wb status: 0x%x\n",831			dst_func, wb_status);832		errcode = MBOX_STATUS_ERRCODE(wb_status);833		return errcode ? errcode : -EFAULT;834	}835 836	return 0;837}838 839static int send_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,840			     enum hinic_mod_type mod, u16 cmd, void *msg,841			     u16 msg_len, u16 dst_func,842			     enum hinic_hwif_direction_type direction,843			     enum hinic_mbox_ack_type ack_type,844			     struct mbox_msg_info *msg_info)845{846	struct hinic_hwdev *hwdev = func_to_func->hwdev;847	u16 seg_len = MBOX_SEG_LEN;848	u8 *msg_seg = (u8 *)msg;849	u16 left = msg_len;850	u32 seq_id = 0;851	u64 header = 0;852	int err = 0;853 854	down(&func_to_func->msg_send_sem);855 856	header = HINIC_MBOX_HEADER_SET(msg_len, MSG_LEN) |857		 HINIC_MBOX_HEADER_SET(mod, MODULE) |858		 HINIC_MBOX_HEADER_SET(seg_len, SEG_LEN) |859		 HINIC_MBOX_HEADER_SET(ack_type, NO_ACK) |860		 HINIC_MBOX_HEADER_SET(SEQ_ID_START_VAL, SEQID) |861		 HINIC_MBOX_HEADER_SET(NOT_LAST_SEG, LAST) |862		 HINIC_MBOX_HEADER_SET(direction, DIRECTION) |863		 HINIC_MBOX_HEADER_SET(cmd, CMD) |864		 /* The vf's offset to it's associated pf */865		 HINIC_MBOX_HEADER_SET(msg_info->msg_id, MSG_ID) |866		 HINIC_MBOX_HEADER_SET(msg_info->status, STATUS) |867		 HINIC_MBOX_HEADER_SET(hinic_global_func_id_hw(hwdev->hwif),868				       SRC_GLB_FUNC_IDX);869 870	while (!(HINIC_MBOX_HEADER_GET(header, LAST))) {871		if (left <= HINIC_MBOX_SEG_LEN) {872			header &= ~MBOX_SEGLEN_MASK;873			header |= HINIC_MBOX_HEADER_SET(left, SEG_LEN);874			header |= HINIC_MBOX_HEADER_SET(LAST_SEG, LAST);875 876			seg_len = left;877		}878 879		err = send_mbox_seg(func_to_func, header, dst_func, msg_seg,880				    seg_len, MBOX_SEND_MSG_INT, msg_info);881		if (err) {882			dev_err(&hwdev->hwif->pdev->dev, "Failed to send mbox seg, seq_id=0x%llx\n",883				HINIC_MBOX_HEADER_GET(header, SEQID));884			goto err_send_mbox_seg;885		}886 887		left -= HINIC_MBOX_SEG_LEN;888		msg_seg += HINIC_MBOX_SEG_LEN;889 890		seq_id++;891		header &= ~(HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEQID_MASK,892						  SEQID));893		header |= HINIC_MBOX_HEADER_SET(seq_id, SEQID);894	}895 896err_send_mbox_seg:897	up(&func_to_func->msg_send_sem);898 899	return err;900}901 902static void903response_for_recv_func_mbox(struct hinic_mbox_func_to_func *func_to_func,904			    struct hinic_recv_mbox *recv_mbox, int err,905			    u16 out_size, u16 src_func_idx)906{907	struct mbox_msg_info msg_info = {0};908 909	if (recv_mbox->ack_type == MBOX_ACK) {910		msg_info.msg_id = recv_mbox->msg_info.msg_id;911		if (err == HINIC_MBOX_PF_BUSY_ACTIVE_FW)912			msg_info.status = HINIC_MBOX_PF_BUSY_ACTIVE_FW;913		else if (err == HINIC_MBOX_VF_CMD_ERROR)914			msg_info.status = HINIC_MBOX_VF_CMD_ERROR;915		else if (err)916			msg_info.status = HINIC_MBOX_PF_SEND_ERR;917 918		/* if no data needs to response, set out_size to 1 */919		if (!out_size || err)920			out_size = MBOX_MSG_NO_DATA_LEN;921 922		send_mbox_to_func(func_to_func, recv_mbox->mod, recv_mbox->cmd,923				  recv_mbox->buf_out, out_size, src_func_idx,924				  HINIC_HWIF_RESPONSE, MBOX_ACK,925				  &msg_info);926	}927}928 929static void recv_func_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,930				   struct hinic_recv_mbox *recv_mbox,931				   u16 src_func_idx)932{933	void *buf_out = recv_mbox->buf_out;934	u16 out_size = MBOX_MAX_BUF_SZ;935	int err = 0;936 937	if (HINIC_IS_VF(func_to_func->hwif)) {938		err = recv_vf_mbox_handler(func_to_func, recv_mbox, buf_out,939					   &out_size);940	} else {941		if (IS_PF_OR_PPF_SRC(src_func_idx))942			dev_warn(&func_to_func->hwif->pdev->dev,943				 "Unsupported pf2pf mbox msg\n");944		else945			err = recv_pf_from_vf_mbox_handler(func_to_func,946							   recv_mbox,947							   src_func_idx,948							   buf_out, &out_size);949	}950 951	response_for_recv_func_mbox(func_to_func, recv_mbox, err, out_size,952				    src_func_idx);953	kfree(recv_mbox->buf_out);954	kfree(recv_mbox->mbox);955	kfree(recv_mbox);956}957 958static void set_mbox_to_func_event(struct hinic_mbox_func_to_func *func_to_func,959				   enum mbox_event_state event_flag)960{961	spin_lock(&func_to_func->mbox_lock);962	func_to_func->event_flag = event_flag;963	spin_unlock(&func_to_func->mbox_lock);964}965 966static int mbox_resp_info_handler(struct hinic_mbox_func_to_func *func_to_func,967				  struct hinic_recv_mbox *mbox_for_resp,968				  enum hinic_mod_type mod, u16 cmd,969				  void *buf_out, u16 *out_size)970{971	int err;972 973	if (mbox_for_resp->msg_info.status) {974		err = mbox_for_resp->msg_info.status;975		if (err != HINIC_MBOX_PF_BUSY_ACTIVE_FW)976			dev_err(&func_to_func->hwif->pdev->dev, "Mbox response error(0x%x)\n",977				mbox_for_resp->msg_info.status);978		return err;979	}980 981	if (buf_out && out_size) {982		if (*out_size < mbox_for_resp->mbox_len) {983			dev_err(&func_to_func->hwif->pdev->dev,984				"Invalid response mbox message length: %d for mod %d cmd %d, should less than: %d\n",985				mbox_for_resp->mbox_len, mod, cmd, *out_size);986			return -EFAULT;987		}988 989		if (mbox_for_resp->mbox_len)990			memcpy(buf_out, mbox_for_resp->mbox,991			       mbox_for_resp->mbox_len);992 993		*out_size = mbox_for_resp->mbox_len;994	}995 996	return 0;997}998 999int hinic_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,1000		       enum hinic_mod_type mod, u16 cmd, u16 dst_func,1001		       void *buf_in, u16 in_size, void *buf_out,1002		       u16 *out_size, u32 timeout)1003{1004	struct hinic_recv_mbox *mbox_for_resp;1005	struct mbox_msg_info msg_info = {0};1006	unsigned long timeo;1007	int err;1008 1009	mbox_for_resp = &func_to_func->mbox_resp[dst_func];1010 1011	down(&func_to_func->mbox_send_sem);1012 1013	init_completion(&mbox_for_resp->recv_done);1014 1015	msg_info.msg_id = MBOX_MSG_ID_INC(func_to_func);1016 1017	set_mbox_to_func_event(func_to_func, EVENT_START);1018 1019	err = send_mbox_to_func(func_to_func, mod, cmd, buf_in, in_size,1020				dst_func, HINIC_HWIF_DIRECT_SEND, MBOX_ACK,1021				&msg_info);1022	if (err) {1023		dev_err(&func_to_func->hwif->pdev->dev, "Send mailbox failed, msg_id: %d\n",1024			msg_info.msg_id);1025		set_mbox_to_func_event(func_to_func, EVENT_FAIL);1026		goto err_send_mbox;1027	}1028 1029	timeo = msecs_to_jiffies(timeout ? timeout : HINIC_MBOX_COMP_TIME);1030	if (!wait_for_completion_timeout(&mbox_for_resp->recv_done, timeo)) {1031		set_mbox_to_func_event(func_to_func, EVENT_TIMEOUT);1032		dev_err(&func_to_func->hwif->pdev->dev,1033			"Send mbox msg timeout, msg_id: %d\n", msg_info.msg_id);1034		hinic_dump_aeq_info(func_to_func->hwdev);1035		err = -ETIMEDOUT;1036		goto err_send_mbox;1037	}1038 1039	set_mbox_to_func_event(func_to_func, EVENT_END);1040 1041	err = mbox_resp_info_handler(func_to_func, mbox_for_resp, mod, cmd,1042				     buf_out, out_size);1043 1044err_send_mbox:1045	up(&func_to_func->mbox_send_sem);1046 1047	return err;1048}1049 1050static int mbox_func_params_valid(struct hinic_mbox_func_to_func *func_to_func,1051				  void *buf_in, u16 in_size)1052{1053	if (in_size > HINIC_MBOX_DATA_SIZE) {1054		dev_err(&func_to_func->hwif->pdev->dev,1055			"Mbox msg len(%d) exceed limit(%d)\n",1056			in_size, HINIC_MBOX_DATA_SIZE);1057		return -EINVAL;1058	}1059 1060	return 0;1061}1062 1063int hinic_mbox_to_pf(struct hinic_hwdev *hwdev,1064		     enum hinic_mod_type mod, u8 cmd, void *buf_in,1065		     u16 in_size, void *buf_out, u16 *out_size, u32 timeout)1066{1067	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;1068	int err = mbox_func_params_valid(func_to_func, buf_in, in_size);1069 1070	if (err)1071		return err;1072 1073	if (!HINIC_IS_VF(hwdev->hwif)) {1074		dev_err(&hwdev->hwif->pdev->dev, "Params error, func_type: %d\n",1075			HINIC_FUNC_TYPE(hwdev->hwif));1076		return -EINVAL;1077	}1078 1079	return hinic_mbox_to_func(func_to_func, mod, cmd,1080				  hinic_pf_id_of_vf_hw(hwdev->hwif), buf_in,1081				  in_size, buf_out, out_size, timeout);1082}1083 1084int hinic_mbox_to_vf(struct hinic_hwdev *hwdev,1085		     enum hinic_mod_type mod, u16 vf_id, u8 cmd, void *buf_in,1086		     u16 in_size, void *buf_out, u16 *out_size, u32 timeout)1087{1088	struct hinic_mbox_func_to_func *func_to_func;1089	u16 dst_func_idx;1090	int err;1091 1092	if (!hwdev)1093		return -EINVAL;1094 1095	func_to_func = hwdev->func_to_func;1096	err = mbox_func_params_valid(func_to_func, buf_in, in_size);1097	if (err)1098		return err;1099 1100	if (HINIC_IS_VF(hwdev->hwif)) {1101		dev_err(&hwdev->hwif->pdev->dev, "Params error, func_type: %d\n",1102			HINIC_FUNC_TYPE(hwdev->hwif));1103		return -EINVAL;1104	}1105 1106	if (!vf_id) {1107		dev_err(&hwdev->hwif->pdev->dev,1108			"VF id(%d) error!\n", vf_id);1109		return -EINVAL;1110	}1111 1112	/* vf_offset_to_pf + vf_id is the vf's global function id of vf in1113	 * this pf1114	 */1115	dst_func_idx = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;1116 1117	return hinic_mbox_to_func(func_to_func, mod, cmd, dst_func_idx, buf_in,1118				  in_size, buf_out, out_size, timeout);1119}1120 1121static int init_mbox_info(struct hinic_recv_mbox *mbox_info)1122{1123	int err;1124 1125	mbox_info->seq_id = SEQ_ID_MAX_VAL;1126 1127	mbox_info->mbox = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);1128	if (!mbox_info->mbox)1129		return -ENOMEM;1130 1131	mbox_info->buf_out = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);1132	if (!mbox_info->buf_out) {1133		err = -ENOMEM;1134		goto err_alloc_buf_out;1135	}1136 1137	atomic_set(&mbox_info->msg_cnt, 0);1138 1139	return 0;1140 1141err_alloc_buf_out:1142	kfree(mbox_info->mbox);1143 1144	return err;1145}1146 1147static void clean_mbox_info(struct hinic_recv_mbox *mbox_info)1148{1149	kfree(mbox_info->buf_out);1150	kfree(mbox_info->mbox);1151}1152 1153static int alloc_mbox_info(struct hinic_hwdev *hwdev,1154			   struct hinic_recv_mbox *mbox_info)1155{1156	u16 func_idx, i;1157	int err;1158 1159	for (func_idx = 0; func_idx < HINIC_MAX_FUNCTIONS; func_idx++) {1160		err = init_mbox_info(&mbox_info[func_idx]);1161		if (err) {1162			dev_err(&hwdev->hwif->pdev->dev, "Failed to init function %d mbox info\n",1163				func_idx);1164			goto err_init_mbox_info;1165		}1166	}1167 1168	return 0;1169 1170err_init_mbox_info:1171	for (i = 0; i < func_idx; i++)1172		clean_mbox_info(&mbox_info[i]);1173 1174	return err;1175}1176 1177static void free_mbox_info(struct hinic_recv_mbox *mbox_info)1178{1179	u16 func_idx;1180 1181	for (func_idx = 0; func_idx < HINIC_MAX_FUNCTIONS; func_idx++)1182		clean_mbox_info(&mbox_info[func_idx]);1183}1184 1185static void prepare_send_mbox(struct hinic_mbox_func_to_func *func_to_func)1186{1187	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;1188 1189	send_mbox->data = MBOX_AREA(func_to_func->hwif);1190}1191 1192static int alloc_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func)1193{1194	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;1195	struct hinic_hwdev *hwdev = func_to_func->hwdev;1196	u32 addr_h, addr_l;1197 1198	send_mbox->wb_vaddr = dma_alloc_coherent(&hwdev->hwif->pdev->dev,1199						 MBOX_WB_STATUS_LEN,1200						 &send_mbox->wb_paddr,1201						 GFP_KERNEL);1202	if (!send_mbox->wb_vaddr)1203		return -ENOMEM;1204 1205	send_mbox->wb_status = send_mbox->wb_vaddr;1206 1207	addr_h = upper_32_bits(send_mbox->wb_paddr);1208	addr_l = lower_32_bits(send_mbox->wb_paddr);1209 1210	hinic_hwif_write_reg(hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF,1211			     addr_h);1212	hinic_hwif_write_reg(hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF,1213			     addr_l);1214 1215	return 0;1216}1217 1218static void free_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func)1219{1220	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;1221	struct hinic_hwdev *hwdev = func_to_func->hwdev;1222 1223	hinic_hwif_write_reg(hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF,1224			     0);1225	hinic_hwif_write_reg(hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF,1226			     0);1227 1228	dma_free_coherent(&hwdev->hwif->pdev->dev, MBOX_WB_STATUS_LEN,1229			  send_mbox->wb_vaddr,1230			  send_mbox->wb_paddr);1231}1232 1233bool hinic_mbox_check_cmd_valid(struct hinic_hwdev *hwdev,1234				struct vf_cmd_check_handle *cmd_handle,1235				u16 vf_id, u8 cmd, void *buf_in,1236				u16 in_size, u8 size)1237{1238	u16 src_idx = vf_id + hinic_glb_pf_vf_offset(hwdev->hwif);1239	int i;1240 1241	for (i = 0; i < size; i++) {1242		if (cmd == cmd_handle[i].cmd) {1243			if (cmd_handle[i].check_cmd)1244				return cmd_handle[i].check_cmd(hwdev, src_idx,1245							       buf_in, in_size);1246			else1247				return true;1248		}1249	}1250 1251	dev_err(&hwdev->hwif->pdev->dev,1252		"PF Receive VF(%d) unsupported cmd(0x%x)\n",1253		vf_id + hinic_glb_pf_vf_offset(hwdev->hwif), cmd);1254 1255	return false;1256}1257 1258static bool hinic_cmdq_check_vf_ctxt(struct hinic_hwdev *hwdev,1259				     struct hinic_cmdq_ctxt *cmdq_ctxt)1260{1261	struct hinic_cmdq_ctxt_info *ctxt_info = &cmdq_ctxt->ctxt_info;1262	u64 curr_pg_pfn, wq_block_pfn;1263 1264	if (cmdq_ctxt->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif) ||1265	    cmdq_ctxt->cmdq_type > HINIC_MAX_CMDQ_TYPES)1266		return false;1267 1268	curr_pg_pfn = HINIC_CMDQ_CTXT_PAGE_INFO_GET1269		(ctxt_info->curr_wqe_page_pfn, CURR_WQE_PAGE_PFN);1270	wq_block_pfn = HINIC_CMDQ_CTXT_BLOCK_INFO_GET1271		(ctxt_info->wq_block_pfn, WQ_BLOCK_PFN);1272	/* VF must use 0-level CLA */1273	if (curr_pg_pfn != wq_block_pfn)1274		return false;1275 1276	return true;1277}1278 1279static bool check_cmdq_ctxt(struct hinic_hwdev *hwdev, u16 func_idx,1280			    void *buf_in, u16 in_size)1281{1282	if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size))1283		return false;1284 1285	return hinic_cmdq_check_vf_ctxt(hwdev, buf_in);1286}1287 1288#define HW_CTX_QPS_VALID(hw_ctxt)   \1289		((hw_ctxt)->rq_depth >= HINIC_QUEUE_MIN_DEPTH &&	\1290		(hw_ctxt)->rq_depth <= HINIC_QUEUE_MAX_DEPTH &&	\1291		(hw_ctxt)->sq_depth >= HINIC_QUEUE_MIN_DEPTH &&	\1292		(hw_ctxt)->sq_depth <= HINIC_QUEUE_MAX_DEPTH &&	\1293		(hw_ctxt)->rx_buf_sz_idx <= HINIC_MAX_RX_BUFFER_SIZE)1294 1295static bool hw_ctxt_qps_param_valid(struct hinic_cmd_hw_ioctxt *hw_ctxt)1296{1297	if (HW_CTX_QPS_VALID(hw_ctxt))1298		return true;1299 1300	if (!hw_ctxt->rq_depth && !hw_ctxt->sq_depth &&1301	    !hw_ctxt->rx_buf_sz_idx)1302		return true;1303 1304	return false;1305}1306 1307static bool check_hwctxt(struct hinic_hwdev *hwdev, u16 func_idx,1308			 void *buf_in, u16 in_size)1309{1310	struct hinic_cmd_hw_ioctxt *hw_ctxt = buf_in;1311 1312	if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size))1313		return false;1314 1315	if (hw_ctxt->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif))1316		return false;1317 1318	if (hw_ctxt->set_cmdq_depth) {1319		if (hw_ctxt->cmdq_depth >= HINIC_QUEUE_MIN_DEPTH &&1320		    hw_ctxt->cmdq_depth <= HINIC_QUEUE_MAX_DEPTH)1321			return true;1322 1323		return false;1324	}1325 1326	return hw_ctxt_qps_param_valid(hw_ctxt);1327}1328 1329static bool check_set_wq_page_size(struct hinic_hwdev *hwdev, u16 func_idx,1330				   void *buf_in, u16 in_size)1331{1332	struct hinic_wq_page_size *page_size_info = buf_in;1333 1334	if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size))1335		return false;1336 1337	if (page_size_info->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif))1338		return false;1339 1340	if (((1U << page_size_info->page_size) * SZ_4K) !=1341	    HINIC_DEFAULT_WQ_PAGE_SIZE)1342		return false;1343 1344	return true;1345}1346 1347static struct vf_cmd_check_handle hw_cmd_support_vf[] = {1348	{HINIC_COMM_CMD_START_FLR, hinic_mbox_check_func_id_8B},1349	{HINIC_COMM_CMD_DMA_ATTR_SET, hinic_mbox_check_func_id_8B},1350	{HINIC_COMM_CMD_CMDQ_CTXT_SET, check_cmdq_ctxt},1351	{HINIC_COMM_CMD_CMDQ_CTXT_GET, check_cmdq_ctxt},1352	{HINIC_COMM_CMD_HWCTXT_SET, check_hwctxt},1353	{HINIC_COMM_CMD_HWCTXT_GET, check_hwctxt},1354	{HINIC_COMM_CMD_SQ_HI_CI_SET, hinic_mbox_check_func_id_8B},1355	{HINIC_COMM_CMD_RES_STATE_SET, hinic_mbox_check_func_id_8B},1356	{HINIC_COMM_CMD_IO_RES_CLEAR, hinic_mbox_check_func_id_8B},1357	{HINIC_COMM_CMD_CEQ_CTRL_REG_WR_BY_UP, hinic_mbox_check_func_id_8B},1358	{HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP, hinic_mbox_check_func_id_8B},1359	{HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP, hinic_mbox_check_func_id_8B},1360	{HINIC_COMM_CMD_L2NIC_RESET, hinic_mbox_check_func_id_8B},1361	{HINIC_COMM_CMD_PAGESIZE_SET, check_set_wq_page_size},1362};1363 1364static int comm_pf_mbox_handler(void *handle, u16 vf_id, u8 cmd, void *buf_in,1365				u16 in_size, void *buf_out, u16 *out_size)1366{1367	u8 size = ARRAY_SIZE(hw_cmd_support_vf);1368	struct hinic_hwdev *hwdev = handle;1369	struct hinic_pfhwdev *pfhwdev;1370	int err = 0;1371 1372	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);1373 1374	if (!hinic_mbox_check_cmd_valid(handle, hw_cmd_support_vf, vf_id, cmd,1375					buf_in, in_size, size)) {1376		dev_err(&hwdev->hwif->pdev->dev,1377			"PF Receive VF: %d common cmd: 0x%x or mbox len: 0x%x is invalid\n",1378			vf_id + hinic_glb_pf_vf_offset(hwdev->hwif), cmd,1379			in_size);1380		return HINIC_MBOX_VF_CMD_ERROR;1381	}1382 1383	if (cmd == HINIC_COMM_CMD_START_FLR) {1384		*out_size = 0;1385	} else {1386		err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,1387					cmd, buf_in, in_size, buf_out, out_size,1388					HINIC_MGMT_MSG_SYNC);1389		if (err && err != HINIC_MBOX_PF_BUSY_ACTIVE_FW)1390			dev_err(&hwdev->hwif->pdev->dev,1391				"PF mbox common callback handler err: %d\n",1392				err);1393	}1394 1395	return err;1396}1397 1398int hinic_func_to_func_init(struct hinic_hwdev *hwdev)1399{1400	struct hinic_mbox_func_to_func *func_to_func;1401	struct hinic_pfhwdev *pfhwdev;1402	int err;1403 1404	pfhwdev =  container_of(hwdev, struct hinic_pfhwdev, hwdev);1405	func_to_func = kzalloc(sizeof(*func_to_func), GFP_KERNEL);1406	if (!func_to_func)1407		return -ENOMEM;1408 1409	hwdev->func_to_func = func_to_func;1410	func_to_func->hwdev = hwdev;1411	func_to_func->hwif = hwdev->hwif;1412	sema_init(&func_to_func->mbox_send_sem, 1);1413	sema_init(&func_to_func->msg_send_sem, 1);1414	spin_lock_init(&func_to_func->mbox_lock);1415	func_to_func->workq = create_singlethread_workqueue(HINIC_MBOX_WQ_NAME);1416	if (!func_to_func->workq) {1417		dev_err(&hwdev->hwif->pdev->dev, "Failed to initialize MBOX workqueue\n");1418		err = -ENOMEM;1419		goto err_create_mbox_workq;1420	}1421 1422	err = alloc_mbox_info(hwdev, func_to_func->mbox_send);1423	if (err) {1424		dev_err(&hwdev->hwif->pdev->dev, "Failed to alloc mem for mbox_active\n");1425		goto err_alloc_mbox_for_send;1426	}1427 1428	err = alloc_mbox_info(hwdev, func_to_func->mbox_resp);1429	if (err) {1430		dev_err(&hwdev->hwif->pdev->dev, "Failed to alloc mem for mbox_passive\n");1431		goto err_alloc_mbox_for_resp;1432	}1433 1434	err = alloc_mbox_wb_status(func_to_func);1435	if (err) {1436		dev_err(&hwdev->hwif->pdev->dev, "Failed to alloc mbox write back status\n");1437		goto err_alloc_wb_status;1438	}1439 1440	prepare_send_mbox(func_to_func);1441 1442	hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MBX_FROM_FUNC,1443				 &pfhwdev->hwdev, hinic_mbox_func_aeqe_handler);1444	hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MBX_SEND_RSLT,1445				 &pfhwdev->hwdev, hinic_mbox_self_aeqe_handler);1446 1447	if (!HINIC_IS_VF(hwdev->hwif))1448		hinic_register_pf_mbox_cb(hwdev, HINIC_MOD_COMM,1449					  comm_pf_mbox_handler);1450 1451	return 0;1452 1453err_alloc_wb_status:1454	free_mbox_info(func_to_func->mbox_resp);1455 1456err_alloc_mbox_for_resp:1457	free_mbox_info(func_to_func->mbox_send);1458 1459err_alloc_mbox_for_send:1460	destroy_workqueue(func_to_func->workq);1461 1462err_create_mbox_workq:1463	kfree(func_to_func);1464 1465	return err;1466}1467 1468void hinic_func_to_func_free(struct hinic_hwdev *hwdev)1469{1470	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;1471 1472	hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MBX_FROM_FUNC);1473	hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MBX_SEND_RSLT);1474 1475	hinic_unregister_pf_mbox_cb(hwdev, HINIC_MOD_COMM);1476	/* destroy workqueue before free related mbox resources in case of1477	 * illegal resource access1478	 */1479	destroy_workqueue(func_to_func->workq);1480 1481	free_mbox_wb_status(func_to_func);1482	free_mbox_info(func_to_func->mbox_resp);1483	free_mbox_info(func_to_func->mbox_send);1484 1485	kfree(func_to_func);1486}1487 1488int hinic_vf_mbox_random_id_init(struct hinic_hwdev *hwdev)1489{1490	u16 vf_offset;1491	u8 vf_in_pf;1492	int err = 0;1493 1494	if (HINIC_IS_VF(hwdev->hwif))1495		return 0;1496 1497	vf_offset = hinic_glb_pf_vf_offset(hwdev->hwif);1498 1499	for (vf_in_pf = 1; vf_in_pf <= hwdev->nic_cap.max_vf; vf_in_pf++) {1500		err = set_vf_mbox_random_id(hwdev, vf_offset + vf_in_pf);1501		if (err)1502			break;1503	}1504 1505	if (err == HINIC_MGMT_CMD_UNSUPPORTED) {1506		hwdev->func_to_func->support_vf_random = false;1507		err = 0;1508		dev_warn(&hwdev->hwif->pdev->dev, "Mgmt is unsupported to set VF%d random id\n",1509			 vf_in_pf - 1);1510	} else if (!err) {1511		hwdev->func_to_func->support_vf_random = true;1512	}1513 1514	return err;1515}1516