// SPDX-License-Identifier: GPL-2.0-only /* * Huawei HiNIC PCI Express Linux driver * Copyright(c) 2017 Huawei Technologies Co., Ltd */ #include <linux/kernel.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/pci.h> #include <linux/device.h> #include <linux/slab.h> #include <linux/dma-mapping.h> #include <linux/bitops.h> #include <linux/err.h> #include <linux/jiffies.h> #include <linux/delay.h> #include <linux/log2.h> #include <linux/semaphore.h> #include <asm/byteorder.h> #include <asm/barrier.h> #include "hinic_hw_csr.h" #include "hinic_hw_if.h" #include "hinic_hw_api_cmd.h" #define API_CHAIN_NUM_CELLS … #define API_CMD_CELL_SIZE_SHIFT … #define API_CMD_CELL_SIZE_MIN … #define API_CMD_CELL_SIZE(cell_size) … #define API_CMD_CELL_SIZE_VAL(size) … #define API_CMD_BUF_SIZE … /* Sizes of the members in hinic_api_cmd_cell */ #define API_CMD_CELL_DESC_SIZE … #define API_CMD_CELL_DATA_ADDR_SIZE … #define API_CMD_CELL_ALIGNMENT … #define API_CMD_TIMEOUT … #define MASKED_IDX(chain, idx) … #define SIZE_8BYTES(size) … #define SIZE_4BYTES(size) … #define RD_DMA_ATTR_DEFAULT … #define WR_DMA_ATTR_DEFAULT … enum api_cmd_data_format { … }; enum api_cmd_type { … }; enum api_cmd_bypass { … }; enum api_cmd_xor_chk_level { … }; static u8 xor_chksum_set(void *data) { … } static void set_prod_idx(struct hinic_api_cmd_chain *chain) { … } static u32 get_hw_cons_idx(struct hinic_api_cmd_chain *chain) { … } static void dump_api_chain_reg(struct hinic_api_cmd_chain *chain) { … } /** * chain_busy - check if the chain is still processing last requests * @chain: chain to check * * Return 0 - Success, negative - Failure **/ static int chain_busy(struct hinic_api_cmd_chain *chain) { … } /** * get_cell_data_size - get the data size of a specific cell type * @type: chain type * * Return the data(Desc + Address) size in the cell **/ static u8 get_cell_data_size(enum hinic_api_cmd_chain_type type) { … } /** * prepare_cell_ctrl - prepare the ctrl of the cell for the command * @cell_ctrl: the control of the cell to set the control value into it * @data_size: the size of the data in the cell **/ static void prepare_cell_ctrl(u64 *cell_ctrl, u16 data_size) { … } /** * prepare_api_cmd - prepare API CMD command * @chain: chain for the command * @dest: destination node on the card that will receive the command * @cmd: command data * @cmd_size: the command size **/ static void prepare_api_cmd(struct hinic_api_cmd_chain *chain, enum hinic_node_id dest, void *cmd, u16 cmd_size) { … } /** * prepare_cell - prepare cell ctrl and cmd in the current cell * @chain: chain for the command * @dest: destination node on the card that will receive the command * @cmd: command data * @cmd_size: the command size * * Return 0 - Success, negative - Failure **/ static void prepare_cell(struct hinic_api_cmd_chain *chain, enum hinic_node_id dest, void *cmd, u16 cmd_size) { … } static inline void cmd_chain_prod_idx_inc(struct hinic_api_cmd_chain *chain) { … } /** * api_cmd_status_update - update the status in the chain struct * @chain: chain to update **/ static void api_cmd_status_update(struct hinic_api_cmd_chain *chain) { … } /** * wait_for_status_poll - wait for write to api cmd command to complete * @chain: the chain of the command * * Return 0 - Success, negative - Failure **/ static int wait_for_status_poll(struct hinic_api_cmd_chain *chain) { … } /** * wait_for_api_cmd_completion - wait for command to complete * @chain: chain for the command * * Return 0 - Success, negative - Failure **/ static int wait_for_api_cmd_completion(struct hinic_api_cmd_chain *chain) { … } /** * api_cmd - API CMD command * @chain: chain for the command * @dest: destination node on the card that will receive the command * @cmd: command data * @cmd_size: the command size * * Return 0 - Success, negative - Failure **/ static int api_cmd(struct hinic_api_cmd_chain *chain, enum hinic_node_id dest, u8 *cmd, u16 cmd_size) { … } /** * hinic_api_cmd_write - Write API CMD command * @chain: chain for write command * @dest: destination node on the card that will receive the command * @cmd: command data * @size: the command size * * Return 0 - Success, negative - Failure **/ int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain, enum hinic_node_id dest, u8 *cmd, u16 size) { … } /** * api_cmd_hw_restart - restart the chain in the HW * @chain: the API CMD specific chain to restart * * Return 0 - Success, negative - Failure **/ static int api_cmd_hw_restart(struct hinic_api_cmd_chain *chain) { … } /** * api_cmd_ctrl_init - set the control register of a chain * @chain: the API CMD specific chain to set control register for **/ static void api_cmd_ctrl_init(struct hinic_api_cmd_chain *chain) { … } /** * api_cmd_set_status_addr - set the status address of a chain in the HW * @chain: the API CMD specific chain to set in HW status address for **/ static void api_cmd_set_status_addr(struct hinic_api_cmd_chain *chain) { … } /** * api_cmd_set_num_cells - set the number cells of a chain in the HW * @chain: the API CMD specific chain to set in HW the number of cells for **/ static void api_cmd_set_num_cells(struct hinic_api_cmd_chain *chain) { … } /** * api_cmd_head_init - set the head of a chain in the HW * @chain: the API CMD specific chain to set in HW the head for **/ static void api_cmd_head_init(struct hinic_api_cmd_chain *chain) { … } /** * api_cmd_chain_hw_clean - clean the HW * @chain: the API CMD specific chain **/ static void api_cmd_chain_hw_clean(struct hinic_api_cmd_chain *chain) { … } /** * api_cmd_chain_hw_init - initialize the chain in the HW * @chain: the API CMD specific chain to initialize in HW * * Return 0 - Success, negative - Failure **/ static int api_cmd_chain_hw_init(struct hinic_api_cmd_chain *chain) { … } /** * free_cmd_buf - free the dma buffer of API CMD command * @chain: the API CMD specific chain of the cmd * @cell_idx: the cell index of the cmd **/ static void free_cmd_buf(struct hinic_api_cmd_chain *chain, int cell_idx) { … } /** * alloc_cmd_buf - allocate a dma buffer for API CMD command * @chain: the API CMD specific chain for the cmd * @cell: the cell in the HW for the cmd * @cell_idx: the index of the cell * * Return 0 - Success, negative - Failure **/ static int alloc_cmd_buf(struct hinic_api_cmd_chain *chain, struct hinic_api_cmd_cell *cell, int cell_idx) { … } /** * api_cmd_create_cell - create API CMD cell for specific chain * @chain: the API CMD specific chain to create its cell * @cell_idx: the index of the cell to create * @pre_node: previous cell * @node_vaddr: the returned virt addr of the cell * * Return 0 - Success, negative - Failure **/ static int api_cmd_create_cell(struct hinic_api_cmd_chain *chain, int cell_idx, struct hinic_api_cmd_cell *pre_node, struct hinic_api_cmd_cell **node_vaddr) { … } /** * api_cmd_destroy_cell - destroy API CMD cell of specific chain * @chain: the API CMD specific chain to destroy its cell * @cell_idx: the cell to destroy **/ static void api_cmd_destroy_cell(struct hinic_api_cmd_chain *chain, int cell_idx) { … } /** * api_cmd_destroy_cells - destroy API CMD cells of specific chain * @chain: the API CMD specific chain to destroy its cells * @num_cells: number of cells to destroy **/ static void api_cmd_destroy_cells(struct hinic_api_cmd_chain *chain, int num_cells) { … } /** * api_cmd_create_cells - create API CMD cells for specific chain * @chain: the API CMD specific chain * * Return 0 - Success, negative - Failure **/ static int api_cmd_create_cells(struct hinic_api_cmd_chain *chain) { … } /** * api_chain_init - initialize API CMD specific chain * @chain: the API CMD specific chain to initialize * @attr: attributes to set in the chain * * Return 0 - Success, negative - Failure **/ static int api_chain_init(struct hinic_api_cmd_chain *chain, struct hinic_api_cmd_chain_attr *attr) { … } /** * api_chain_free - free API CMD specific chain * @chain: the API CMD specific chain to free **/ static void api_chain_free(struct hinic_api_cmd_chain *chain) { … } /** * api_cmd_create_chain - create API CMD specific chain * @attr: attributes to set the chain * * Return the created chain **/ static struct hinic_api_cmd_chain * api_cmd_create_chain(struct hinic_api_cmd_chain_attr *attr) { … } /** * api_cmd_destroy_chain - destroy API CMD specific chain * @chain: the API CMD specific chain to destroy **/ static void api_cmd_destroy_chain(struct hinic_api_cmd_chain *chain) { … } /** * hinic_api_cmd_init - Initialize all the API CMD chains * @chain: the API CMD chains that are initialized * @hwif: the hardware interface of a pci function device * * Return 0 - Success, negative - Failure **/ int hinic_api_cmd_init(struct hinic_api_cmd_chain **chain, struct hinic_hwif *hwif) { … } /** * hinic_api_cmd_free - free the API CMD chains * @chain: the API CMD chains that are freed **/ void hinic_api_cmd_free(struct hinic_api_cmd_chain **chain) { … }