Commit 53200a86 authored by Fan Gong's avatar Fan Gong Committed by Paolo Abeni
Browse files

hinic3: Add PF framework

parent c5e7b1d1
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#define _HINIC3_CSR_H_

#define HINIC3_CFG_REGS_FLAG                  0x40000000
#define HINIC3_MGMT_REGS_FLAG                 0xC0000000
#define HINIC3_REGS_FLAG_MASK                 0x3FFFFFFF

#define HINIC3_VF_CFG_REG_OFFSET              0x2000
@@ -24,6 +25,11 @@
#define HINIC3_FUNC_CSR_MAILBOX_RESULT_H_OFF  (HINIC3_CFG_REGS_FLAG + 0x0108)
#define HINIC3_FUNC_CSR_MAILBOX_RESULT_L_OFF  (HINIC3_CFG_REGS_FLAG + 0x010C)

#define HINIC3_HOST_CSR_BASE_ADDR             (HINIC3_MGMT_REGS_FLAG + 0x6000)
#define HINIC3_PPF_ELECTION_OFFSET            0x0
#define HINIC3_CSR_PPF_ELECTION_ADDR  \
	(HINIC3_HOST_CSR_BASE_ADDR + HINIC3_PPF_ELECTION_OFFSET)

#define HINIC3_CSR_DMA_ATTR_TBL_ADDR          (HINIC3_CFG_REGS_FLAG + 0x380)
#define HINIC3_CSR_DMA_ATTR_INDIR_IDX_ADDR    (HINIC3_CFG_REGS_FLAG + 0x390)

+61 −0
Original line number Diff line number Diff line
@@ -314,6 +314,8 @@ int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev)
			ret = -EFAULT;
	}

	hinic3_set_pf_status(hwif, HINIC3_PF_STATUS_FLR_START_FLAG);

	clr_res.func_id = hwif->attr.func_global_idx;
	msg_params.buf_in = &clr_res;
	msg_params.in_size = sizeof(clr_res);
@@ -337,6 +339,65 @@ int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev)
	return ret;
}

int hinic3_set_bdf_ctxt(struct hinic3_hwdev *hwdev,
			struct comm_cmd_bdf_info *bdf_info)
{
	struct mgmt_msg_params msg_params = {};
	int err;

	mgmt_msg_params_init_default(&msg_params, bdf_info, sizeof(*bdf_info));

	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
				       COMM_CMD_SEND_BDF_INFO, &msg_params);
	if (err || bdf_info->head.status) {
		dev_err(hwdev->dev,
			"Failed to set bdf info to fw, err: %d, status: 0x%x\n",
			err, bdf_info->head.status);
		return -EFAULT;
	}

	return 0;
}

static int hinic3_sync_time(struct hinic3_hwdev *hwdev, u64 time)
{
	struct comm_cmd_sync_time time_info = {};
	struct mgmt_msg_params msg_params = {};
	int err;

	time_info.mstime = time;

	mgmt_msg_params_init_default(&msg_params, &time_info,
				     sizeof(time_info));

	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
				       COMM_CMD_SYNC_TIME, &msg_params);
	if (err || time_info.head.status) {
		dev_err(hwdev->dev,
			"Failed to sync time to mgmt, err: %d, status: 0x%x\n",
			err, time_info.head.status);
		return -EFAULT;
	}

	return 0;
}

void hinic3_sync_time_to_fw(struct hinic3_hwdev *hwdev)
{
	struct timespec64 ts = {};
	u64 time;
	int err;

	ktime_get_real_ts64(&ts);
	time = (u64)(ts.tv_sec * MSEC_PER_SEC + ts.tv_nsec / NSEC_PER_MSEC);

	err = hinic3_sync_time(hwdev, time);
	if (err)
		dev_err(hwdev->dev,
			"Synchronize UTC time to firmware failed, err=%d\n",
			err);
}

static int get_hw_rx_buf_size_idx(int rx_buf_sz, u16 *buf_sz_idx)
{
	/* Supported RX buffer sizes in bytes. Configured by array index. */
+4 −0
Original line number Diff line number Diff line
@@ -40,6 +40,10 @@ int hinic3_set_wq_page_size(struct hinic3_hwdev *hwdev, u16 func_idx,
			    u32 page_size);
int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev, u16 cmdq_depth);
int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev);
int hinic3_set_bdf_ctxt(struct hinic3_hwdev *hwdev,
			struct comm_cmd_bdf_info *bdf_info);
void hinic3_sync_time_to_fw(struct hinic3_hwdev *hwdev);

int hinic3_set_root_ctxt(struct hinic3_hwdev *hwdev, u32 rq_depth, u32 sq_depth,
			 int rx_buf_sz);
int hinic3_clean_root_ctxt(struct hinic3_hwdev *hwdev);
+22 −0
Original line number Diff line number Diff line
@@ -110,6 +110,10 @@ enum comm_cmd {
	COMM_CMD_CFG_MSIX_CTRL_REG       = 23,
	COMM_CMD_SET_CEQ_CTRL_REG        = 24,
	COMM_CMD_SET_DMA_ATTR            = 25,

	/* Commands for obtaining information */
	COMM_CMD_SYNC_TIME               = 62,
	COMM_CMD_SEND_BDF_INFO           = 64,
};

struct comm_cmd_cfg_msix_ctrl_reg {
@@ -251,6 +255,24 @@ struct comm_cmd_clear_resource {
	u16                  rsvd1[3];
};

struct comm_cmd_sync_time {
	struct mgmt_msg_head head;

	u64                  mstime;
	u64                  rsvd1;
};

struct comm_cmd_bdf_info {
	struct mgmt_msg_head head;

	u16                  function_idx;
	u8                   rsvd1[2];
	u8                   bus;
	u8                   device;
	u8                   function;
	u8                   rsvd2[5];
};

/* Services supported by HW. HW uses these values when delivering events.
 * HW supports multiple services that are not yet supported by driver
 * (e.g. RoCE).
+43 −1
Original line number Diff line number Diff line
@@ -13,6 +13,8 @@
#define HINIC3_PCIE_SNOOP        0
#define HINIC3_PCIE_TPH_DISABLE  0

#define HINIC3_SYNFW_TIME_PERIOD  (60 * 60 * 1000)

#define HINIC3_DMA_ATTR_INDIR_IDX_MASK          GENMASK(9, 0)
#define HINIC3_DMA_ATTR_INDIR_IDX_SET(val, member)  \
	FIELD_PREP(HINIC3_DMA_ATTR_INDIR_##member##_MASK, val)
@@ -38,6 +40,7 @@
#define HINIC3_WQ_MAX_REQ       10

enum hinic3_hwdev_init_state {
	HINIC3_HWDEV_MGMT_INITED = 1,
	HINIC3_HWDEV_MBOX_INITED = 2,
	HINIC3_HWDEV_CMDQ_INITED = 3,
};
@@ -419,6 +422,8 @@ static int hinic3_init_comm_ch(struct hinic3_hwdev *hwdev)
		goto err_clear_func_svc_used_state;
	}

	hinic3_set_pf_status(hwdev->hwif, HINIC3_PF_STATUS_ACTIVE_FLAG);

	return 0;

err_clear_func_svc_used_state:
@@ -431,11 +436,43 @@ static int hinic3_init_comm_ch(struct hinic3_hwdev *hwdev)

static void hinic3_uninit_comm_ch(struct hinic3_hwdev *hwdev)
{
	hinic3_set_pf_status(hwdev->hwif, HINIC3_PF_STATUS_INIT);
	hinic3_free_cmdqs_channel(hwdev);
	hinic3_set_func_svc_used_state(hwdev, COMM_FUNC_SVC_T_COMM, 0);
	free_base_mgmt_channel(hwdev);
}

static void hinic3_auto_sync_time_work(struct work_struct *work)
{
	struct delayed_work *delay = to_delayed_work(work);
	struct hinic3_hwdev *hwdev;

	hwdev = container_of(delay, struct hinic3_hwdev, sync_time_task);

	hinic3_sync_time_to_fw(hwdev);

	queue_delayed_work(hwdev->workq, &hwdev->sync_time_task,
			   msecs_to_jiffies(HINIC3_SYNFW_TIME_PERIOD));
}

static void hinic3_init_ppf_work(struct hinic3_hwdev *hwdev)
{
	if (hinic3_ppf_idx(hwdev) != hinic3_global_func_id(hwdev))
		return;

	INIT_DELAYED_WORK(&hwdev->sync_time_task, hinic3_auto_sync_time_work);
	queue_delayed_work(hwdev->workq, &hwdev->sync_time_task,
			   msecs_to_jiffies(HINIC3_SYNFW_TIME_PERIOD));
}

static void hinic3_free_ppf_work(struct hinic3_hwdev *hwdev)
{
	if (hinic3_ppf_idx(hwdev) != hinic3_global_func_id(hwdev))
		return;

	disable_delayed_work_sync(&hwdev->sync_time_task);
}

static DEFINE_IDA(hinic3_adev_ida);

static int hinic3_adev_idx_alloc(void)
@@ -498,15 +535,19 @@ int hinic3_init_hwdev(struct pci_dev *pdev)
		goto err_uninit_comm_ch;
	}

	hinic3_init_ppf_work(hwdev);

	err = hinic3_set_comm_features(hwdev, hwdev->features,
				       COMM_MAX_FEATURE_QWORD);
	if (err) {
		dev_err(hwdev->dev, "Failed to set comm features\n");
		goto err_uninit_comm_ch;
		goto err_free_ppf_work;
	}

	return 0;

err_free_ppf_work:
	hinic3_free_ppf_work(hwdev);
err_uninit_comm_ch:
	hinic3_uninit_comm_ch(hwdev);
err_free_cfg_mgmt:
@@ -528,6 +569,7 @@ void hinic3_free_hwdev(struct hinic3_hwdev *hwdev)
	u64 drv_features[COMM_MAX_FEATURE_QWORD] = {};

	hinic3_set_comm_features(hwdev, drv_features, COMM_MAX_FEATURE_QWORD);
	hinic3_free_ppf_work(hwdev);
	hinic3_func_rx_tx_flush(hwdev);
	hinic3_uninit_comm_ch(hwdev);
	hinic3_free_cfg_mgmt(hwdev);
Loading