// SPDX-License-Identifier: GPL-2.0-only
/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*/
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/completion.h>
#include <linux/semaphore.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include "hinic_hw_if.h"
#include "hinic_hw_mgmt.h"
#include "hinic_hw_csr.h"
#include "hinic_hw_dev.h"
#include "hinic_hw_mbox.h"
#define HINIC_MBOX_INT_DST_FUNC_SHIFT 0
#define HINIC_MBOX_INT_DST_AEQN_SHIFT 10
#define HINIC_MBOX_INT_SRC_RESP_AEQN_SHIFT 12
#define HINIC_MBOX_INT_STAT_DMA_SHIFT 14
/* The size of data to be sended (unit of 4 bytes) */
#define HINIC_MBOX_INT_TX_SIZE_SHIFT 20
/* SO_RO(strong order, relax order) */
#define HINIC_MBOX_INT_STAT_DMA_SO_RO_SHIFT 25
#define HINIC_MBOX_INT_WB_EN_SHIFT 28
#define HINIC_MBOX_INT_DST_FUNC_MASK 0x3FF
#define HINIC_MBOX_INT_DST_AEQN_MASK 0x3
#define HINIC_MBOX_INT_SRC_RESP_AEQN_MASK 0x3
#define HINIC_MBOX_INT_STAT_DMA_MASK 0x3F
#define HINIC_MBOX_INT_TX_SIZE_MASK 0x1F
#define HINIC_MBOX_INT_STAT_DMA_SO_RO_MASK 0x3
#define HINIC_MBOX_INT_WB_EN_MASK 0x1
#define HINIC_MBOX_INT_SET(val, field) \
(((val) & HINIC_MBOX_INT_##field##_MASK) << \
HINIC_MBOX_INT_##field##_SHIFT)
enum hinic_mbox_tx_status {
TX_NOT_DONE = 1,
};
#define HINIC_MBOX_CTRL_TRIGGER_AEQE_SHIFT 0
/* specifies the issue request for the message data.
* 0 - Tx request is done;
* 1 - Tx request is in process.
*/
#define HINIC_MBOX_CTRL_TX_STATUS_SHIFT 1
#define HINIC_MBOX_CTRL_TRIGGER_AEQE_MASK 0x1
#define HINIC_MBOX_CTRL_TX_STATUS_MASK 0x1
#define HINIC_MBOX_CTRL_SET(val, field) \
(((val) & HINIC_MBOX_CTRL_##field##_MASK) << \
HINIC_MBOX_CTRL_##field##_SHIFT)
#define HINIC_MBOX_HEADER_MSG_LEN_SHIFT 0
#define HINIC_MBOX_HEADER_MODULE_SHIFT 11
#define HINIC_MBOX_HEADER_SEG_LEN_SHIFT 16
#define HINIC_MBOX_HEADER_NO_ACK_SHIFT 22
#define HINIC_MBOX_HEADER_SEQID_SHIFT 24
#define HINIC_MBOX_HEADER_LAST_SHIFT 30
/* specifies the mailbox message direction
* 0 - send
* 1 - receive
*/
#define HINIC_MBOX_HEADER_DIRECTION_SHIFT 31
#define HINIC_MBOX_HEADER_CMD_SHIFT 32
#define HINIC_MBOX_HEADER_MSG_ID_SHIFT 40
#define HINIC_MBOX_HEADER_STATUS_SHIFT 48
#define HINIC_MBOX_HEADER_SRC_GLB_FUNC_IDX_SHIFT 54
#define HINIC_MBOX_HEADER_MSG_LEN_MASK 0x7FF
#define HINIC_MBOX_HEADER_MODULE_MASK 0x1F
#define HINIC_MBOX_HEADER_SEG_LEN_MASK 0x3F
#define HINIC_MBOX_HEADER_NO_ACK_MASK 0x1
#define HINIC_MBOX_HEADER_SEQID_MASK 0x3F
#define HINIC_MBOX_HEADER_LAST_MASK 0x1
#define HINIC_MBOX_HEADER_DIRECTION_MASK 0x1
#define HINIC_MBOX_HEADER_CMD_MASK 0xFF
#define HINIC_MBOX_HEADER_MSG_ID_MASK 0xFF
#define HINIC_MBOX_HEADER_STATUS_MASK 0x3F
#define HINIC_MBOX_HEADER_SRC_GLB_FUNC_IDX_MASK 0x3FF
#define HINIC_MBOX_HEADER_GET(val, field) \
(((val) >> HINIC_MBOX_HEADER_##field##_SHIFT) & \
HINIC_MBOX_HEADER_##field##_MASK)
#define HINIC_MBOX_HEADER_SET(val, field) \
((u64)((val) & HINIC_MBOX_HEADER_##field##_MASK) << \
HINIC_MBOX_HEADER_##field##_SHIFT)
#define MBOX_SEGLEN_MASK \
HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEG_LEN_MASK, SEG_LEN)
#define HINIC_MBOX_SEG_LEN 48
#define HINIC_MBOX_COMP_TIME 8000U
#define MBOX_MSG_POLLING_TIMEOUT 8000
#define HINIC_MBOX_DATA_SIZE 2040
#define MBOX_MAX_BUF_SZ 2048UL
#define MBOX_HEADER_SZ 8
#define MBOX_INFO_SZ 4
/* MBOX size is 64B, 8B for mbox_header, 4B reserved */
#define MBOX_SEG_LEN 48
#define MBOX_SEG_LEN_ALIGN 4
#define MBOX_WB_STATUS_LEN 16UL
/* mbox write back status is 16B, only first 4B is used */
#define MBOX_WB_STATUS_ERRCODE_MASK 0xFFFF
#define MBOX_WB_STATUS_MASK 0xFF
#define MBOX_WB_ERROR_CODE_MASK 0xFF00
#define MBOX_WB_STATUS_FINISHED_SUCCESS 0xFF
#define MBOX_WB_STATUS_FINISHED_WITH_ERR 0xFE
#define MBOX_WB_STATUS_NOT_FINISHED 0x00
#define MBOX_STATUS_FINISHED(wb) \
(((wb) & MBOX_WB_STATUS_MASK) != MBOX_WB_STATUS_NOT_FINISHED)
#define MBOX_STATUS_SUCCESS(wb) \
(((wb) & MBOX_WB_STATUS_MASK) == MBOX_WB_STATUS_FINISHED_SUCCESS)
#define MBOX_STATUS_ERRCODE(wb) \
((wb) & MBOX_WB_ERROR_CODE_MASK)
#define SEQ_ID_START_VAL 0
#define SEQ_ID_MAX_VAL 42
#define DST_AEQ_IDX_DEFAULT_VAL 0
#define SRC_AEQ_IDX_DEFAULT_VAL 0
#define NO_DMA_ATTRIBUTE_VAL 0
#define HINIC_MGMT_RSP_AEQN 0
#define HINIC_MBOX_RSP_AEQN 2
#define HINIC_MBOX_RECV_AEQN 0
#define MBOX_MSG_NO_DATA_LEN 1
#define MBOX_BODY_FROM_HDR(header) ((u8 *)(header) + MBOX_HEADER_SZ)
#define MBOX_AREA(hwif) \
((hwif)->cfg_regs_bar + HINIC_FUNC_CSR_MAILBOX_DATA_OFF)
#define IS_PF_OR_PPF_SRC(src_func_idx) ((src_func_idx) < HINIC_MAX_PF_FUNCS)
#define MBOX_RESPONSE_ERROR 0x1
#define MBOX_MSG_ID_MASK 0xFF
#define MBOX_MSG_ID(func_to_func) ((func_to_func)->send_msg_id)
#define MBOX_MSG_ID_INC(func_to_func_mbox) (MBOX_MSG_ID(func_to_func_mbox) = \
(MBOX_MSG_ID(func_to_func_mbox) + 1) & MBOX_MSG_ID_MASK)
#define FUNC_ID_OFF_SET_8B 8
#define FUNC_ID_OFF_SET_10B 10
/* max message counter wait to process for one function */
#define HINIC_MAX_MSG_CNT_TO_PROCESS 10
#define HINIC_QUEUE_MIN_DEPTH 6
#define HINIC_QUEUE_MAX_DEPTH 12
#define HINIC_MAX_RX_BUFFER_SIZE 15
enum hinic_hwif_direction_type