Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3dcea321 authored by Aviad Krawczyk's avatar Aviad Krawczyk Committed by David S. Miller
Browse files

net-next/hinic: Initialize api cmd hw



Update the hardware about api cmd resources and initialize it.

Signed-off-by: default avatarAviad Krawczyk <aviad.krawczyk@huawei.com>
Signed-off-by: default avatarZhao Chen <zhaochen6@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eabf0fad
Loading
Loading
Loading
Loading
+172 −1
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
 *
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/pci.h>
@@ -21,8 +22,12 @@
#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 <asm/byteorder.h>

#include "hinic_hw_csr.h"
#include "hinic_hw_if.h"
#include "hinic_hw_api_cmd.h"

@@ -35,8 +40,157 @@
		(((cell_size) >= API_CMD_CELL_SIZE_MIN) ? \
		 (1 << (fls(cell_size - 1))) : API_CMD_CELL_SIZE_MIN)

#define API_CMD_CELL_SIZE_VAL(size)             \
		ilog2((size) >> API_CMD_CELL_SIZE_SHIFT)

#define API_CMD_BUF_SIZE                        2048

#define API_CMD_TIMEOUT                 1000

enum api_cmd_xor_chk_level {
	XOR_CHK_DIS = 0,

	XOR_CHK_ALL = 3,
};

/**
 * 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)
{
	struct hinic_hwif *hwif = chain->hwif;
	int err = -ETIMEDOUT;
	unsigned long end;
	u32 reg_addr, val;

	/* Read Modify Write */
	reg_addr = HINIC_CSR_API_CMD_CHAIN_REQ_ADDR(chain->chain_type);
	val = hinic_hwif_read_reg(hwif, reg_addr);

	val = HINIC_API_CMD_CHAIN_REQ_CLEAR(val, RESTART);
	val |= HINIC_API_CMD_CHAIN_REQ_SET(1, RESTART);

	hinic_hwif_write_reg(hwif, reg_addr, val);

	end = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT);
	do {
		val = hinic_hwif_read_reg(hwif, reg_addr);

		if (!HINIC_API_CMD_CHAIN_REQ_GET(val, RESTART)) {
			err = 0;
			break;
		}

		msleep(20);
	} while (time_before(jiffies, end));

	return err;
}

/**
 * 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)
{
	struct hinic_hwif *hwif = chain->hwif;
	u32 addr, ctrl;
	u16 cell_size;

	/* Read Modify Write */
	addr = HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type);

	cell_size = API_CMD_CELL_SIZE_VAL(chain->cell_size);

	ctrl = hinic_hwif_read_reg(hwif, addr);

	ctrl =  HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_WB_STAT) &
		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR)         &
		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN)         &
		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN)      &
		HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE);

	ctrl |= HINIC_API_CMD_CHAIN_CTRL_SET(1, XOR_ERR)              |
		HINIC_API_CMD_CHAIN_CTRL_SET(XOR_CHK_ALL, XOR_CHK_EN) |
		HINIC_API_CMD_CHAIN_CTRL_SET(cell_size, CELL_SIZE);

	hinic_hwif_write_reg(hwif, addr, ctrl);
}

/**
 * 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)
{
	struct hinic_hwif *hwif = chain->hwif;
	u32 addr, val;

	addr = HINIC_CSR_API_CMD_STATUS_HI_ADDR(chain->chain_type);
	val = upper_32_bits(chain->wb_status_paddr);
	hinic_hwif_write_reg(hwif, addr, val);

	addr = HINIC_CSR_API_CMD_STATUS_LO_ADDR(chain->chain_type);
	val = lower_32_bits(chain->wb_status_paddr);
	hinic_hwif_write_reg(hwif, addr, val);
}

/**
 * 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)
{
	struct hinic_hwif *hwif = chain->hwif;
	u32 addr, val;

	addr = HINIC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(chain->chain_type);
	val  = chain->num_cells;
	hinic_hwif_write_reg(hwif, addr, val);
}

/**
 * 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)
{
	struct hinic_hwif *hwif = chain->hwif;
	u32 addr, val;

	addr = HINIC_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(chain->chain_type);
	val = upper_32_bits(chain->head_cell_paddr);
	hinic_hwif_write_reg(hwif, addr, val);

	addr = HINIC_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(chain->chain_type);
	val = lower_32_bits(chain->head_cell_paddr);
	hinic_hwif_write_reg(hwif, addr, val);
}

/**
 * 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)
{
	struct hinic_hwif *hwif = chain->hwif;
	u32 addr, ctrl;

	addr = HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type);

	ctrl = hinic_hwif_read_reg(hwif, addr);
	ctrl = HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_WB_STAT) &
	       HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR)         &
	       HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN)         &
	       HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN)      &
	       HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE);

	hinic_hwif_write_reg(hwif, addr, ctrl);
}

/**
 * api_cmd_chain_hw_init - initialize the chain in the HW
 * @chain: the API CMD specific chain to initialize in HW
@@ -45,7 +199,23 @@
 **/
static int api_cmd_chain_hw_init(struct hinic_api_cmd_chain *chain)
{
	/* should be implemented */
	struct hinic_hwif *hwif = chain->hwif;
	struct pci_dev *pdev = hwif->pdev;
	int err;

	api_cmd_chain_hw_clean(chain);

	api_cmd_set_status_addr(chain);

	err = api_cmd_hw_restart(chain);
	if (err) {
		dev_err(&pdev->dev, "Failed to restart API CMD HW\n");
		return err;
	}

	api_cmd_ctrl_init(chain);
	api_cmd_set_num_cells(chain);
	api_cmd_head_init(chain);
	return 0;
}

@@ -373,6 +543,7 @@ static struct hinic_api_cmd_chain *
 **/
static void api_cmd_destroy_chain(struct hinic_api_cmd_chain *chain)
{
	api_cmd_chain_hw_clean(chain);
	api_cmd_destroy_cells(chain, chain->num_cells);
	api_chain_free(chain);
}
+38 −0
Original line number Diff line number Diff line
@@ -20,6 +20,44 @@

#include "hinic_hw_if.h"

#define HINIC_API_CMD_CHAIN_REQ_RESTART_SHIFT                   1

#define HINIC_API_CMD_CHAIN_REQ_RESTART_MASK                    0x1

#define HINIC_API_CMD_CHAIN_REQ_SET(val, member)                \
	(((u32)(val) & HINIC_API_CMD_CHAIN_REQ_##member##_MASK) << \
	 HINIC_API_CMD_CHAIN_REQ_##member##_SHIFT)

#define HINIC_API_CMD_CHAIN_REQ_GET(val, member)                \
	(((val) >> HINIC_API_CMD_CHAIN_REQ_##member##_SHIFT) &  \
	 HINIC_API_CMD_CHAIN_REQ_##member##_MASK)

#define HINIC_API_CMD_CHAIN_REQ_CLEAR(val, member)              \
	((val) & (~(HINIC_API_CMD_CHAIN_REQ_##member##_MASK     \
	 << HINIC_API_CMD_CHAIN_REQ_##member##_SHIFT)))

#define HINIC_API_CMD_CHAIN_CTRL_RESTART_WB_STAT_SHIFT          1
#define HINIC_API_CMD_CHAIN_CTRL_XOR_ERR_SHIFT                  2
#define HINIC_API_CMD_CHAIN_CTRL_AEQE_EN_SHIFT                  4
#define HINIC_API_CMD_CHAIN_CTRL_AEQ_ID_SHIFT                   8
#define HINIC_API_CMD_CHAIN_CTRL_XOR_CHK_EN_SHIFT               28
#define HINIC_API_CMD_CHAIN_CTRL_CELL_SIZE_SHIFT                30

#define HINIC_API_CMD_CHAIN_CTRL_RESTART_WB_STAT_MASK           0x1
#define HINIC_API_CMD_CHAIN_CTRL_XOR_ERR_MASK                   0x1
#define HINIC_API_CMD_CHAIN_CTRL_AEQE_EN_MASK                   0x1
#define HINIC_API_CMD_CHAIN_CTRL_AEQ_ID_MASK                    0x3
#define HINIC_API_CMD_CHAIN_CTRL_XOR_CHK_EN_MASK                0x3
#define HINIC_API_CMD_CHAIN_CTRL_CELL_SIZE_MASK                 0x3

#define HINIC_API_CMD_CHAIN_CTRL_SET(val, member)               \
	(((u32)(val) & HINIC_API_CMD_CHAIN_CTRL_##member##_MASK) << \
	 HINIC_API_CMD_CHAIN_CTRL_##member##_SHIFT)

#define HINIC_API_CMD_CHAIN_CTRL_CLEAR(val, member)             \
	((val) & (~(HINIC_API_CMD_CHAIN_CTRL_##member##_MASK    \
	 << HINIC_API_CMD_CHAIN_CTRL_##member##_SHIFT)))

enum hinic_api_cmd_chain_type {
	HINIC_API_CMD_WRITE_TO_MGMT_CPU = 2,

+26 −0
Original line number Diff line number Diff line
@@ -33,4 +33,30 @@
#define HINIC_CSR_PPF_ELECTION_ADDR(idx)                \
	(HINIC_ELECTION_BASE +  (idx) * HINIC_PPF_ELECTION_STRIDE)

/* API CMD registers */
#define HINIC_CSR_API_CMD_BASE                          0xF000

#define HINIC_CSR_API_CMD_STRIDE                        0x100

#define HINIC_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(idx)       \
	(HINIC_CSR_API_CMD_BASE + 0x0 + (idx) * HINIC_CSR_API_CMD_STRIDE)

#define HINIC_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(idx)       \
	(HINIC_CSR_API_CMD_BASE + 0x4 + (idx) * HINIC_CSR_API_CMD_STRIDE)

#define HINIC_CSR_API_CMD_STATUS_HI_ADDR(idx)           \
	(HINIC_CSR_API_CMD_BASE + 0x8 + (idx) * HINIC_CSR_API_CMD_STRIDE)

#define HINIC_CSR_API_CMD_STATUS_LO_ADDR(idx)           \
	(HINIC_CSR_API_CMD_BASE + 0xC + (idx) * HINIC_CSR_API_CMD_STRIDE)

#define HINIC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(idx)     \
	(HINIC_CSR_API_CMD_BASE + 0x10 + (idx) * HINIC_CSR_API_CMD_STRIDE)

#define HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(idx)          \
	(HINIC_CSR_API_CMD_BASE + 0x14 + (idx) * HINIC_CSR_API_CMD_STRIDE)

#define HINIC_CSR_API_CMD_CHAIN_REQ_ADDR(idx)           \
	(HINIC_CSR_API_CMD_BASE + 0x20 + (idx) * HINIC_CSR_API_CMD_STRIDE)

#endif