Commit 7dd29ee1 authored by Luo bin's avatar Luo bin Committed by David S. Miller
Browse files

hinic: add sriov feature support



adds support of basic sriov feature including initialization and
tx/rx capabilities of virtual function

Signed-off-by: default avatarLuo bin <luobin9@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a425b6e1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,4 +4,4 @@ obj-$(CONFIG_HINIC) += hinic.o
hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \
	   hinic_hw_io.o hinic_hw_qp.o hinic_hw_cmdq.o hinic_hw_wq.o \
	   hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o \
	   hinic_common.o hinic_ethtool.o hinic_hw_mbox.o
	   hinic_common.o hinic_ethtool.o hinic_hw_mbox.o hinic_sriov.o
+3 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include "hinic_hw_dev.h"
#include "hinic_tx.h"
#include "hinic_rx.h"
#include "hinic_sriov.h"

#define HINIC_DRV_NAME          "hinic"

@@ -23,6 +24,7 @@ enum hinic_flags {
	HINIC_LINK_UP = BIT(0),
	HINIC_INTF_UP = BIT(1),
	HINIC_RSS_ENABLE = BIT(2),
	HINIC_LINK_DOWN = BIT(3),
};

struct hinic_rx_mode_work {
@@ -78,6 +80,7 @@ struct hinic_dev {
	struct hinic_rss_type		rss_type;
	u8				*rss_hkey_user;
	s32				*rss_indir_user;
	struct hinic_sriov_info sriov_info;
};

#endif
+8 −10
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@
#define CMDQ_WQE_SIZE                   64
#define CMDQ_DEPTH                      SZ_4K

#define CMDQ_WQ_PAGE_SIZE               SZ_4K
#define CMDQ_WQ_PAGE_SIZE               SZ_256K

#define WQE_LCMD_SIZE                   64
#define WQE_SCMD_SIZE                   64
@@ -705,7 +705,7 @@ static void cmdq_init_queue_ctxt(struct hinic_cmdq_ctxt *cmdq_ctxt,
	/* The data in the HW is in Big Endian Format */
	wq_first_page_paddr = be64_to_cpu(*wq->block_vaddr);

	pfn = CMDQ_PFN(wq_first_page_paddr, wq->wq_page_size);
	pfn = CMDQ_PFN(wq_first_page_paddr, SZ_4K);

	ctxt_info->curr_wqe_page_pfn =
		HINIC_CMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN)   |
@@ -714,16 +714,19 @@ static void cmdq_init_queue_ctxt(struct hinic_cmdq_ctxt *cmdq_ctxt,
		HINIC_CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_EN)                |
		HINIC_CMDQ_CTXT_PAGE_INFO_SET(cmdq->wrapped, WRAPPED);

	if (wq->num_q_pages != 1) {
		/* block PFN - Read Modify Write */
		cmdq_first_block_paddr = cmdq_pages->page_paddr;

		pfn = CMDQ_PFN(cmdq_first_block_paddr, wq->wq_page_size);
	}

	ctxt_info->wq_block_pfn =
		HINIC_CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN) |
		HINIC_CMDQ_CTXT_BLOCK_INFO_SET(atomic_read(&wq->cons_idx), CI);

	cmdq_ctxt->func_idx = HINIC_HWIF_FUNC_IDX(cmdqs->hwif);
	cmdq_ctxt->ppf_idx = HINIC_HWIF_PPF_IDX(cmdqs->hwif);
	cmdq_ctxt->cmdq_type  = cmdq->cmdq_type;
}

@@ -795,11 +798,6 @@ static int init_cmdqs_ctxt(struct hinic_hwdev *hwdev,
	size_t cmdq_ctxts_size;
	int err;

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "Unsupported PCI function type\n");
		return -EINVAL;
	}

	cmdq_ctxts_size = HINIC_MAX_CMDQ_TYPES * sizeof(*cmdq_ctxts);
	cmdq_ctxts = devm_kzalloc(&pdev->dev, cmdq_ctxts_size, GFP_KERNEL);
	if (!cmdq_ctxts)
+1 −1
Original line number Diff line number Diff line
@@ -122,7 +122,7 @@ struct hinic_cmdq_ctxt {

	u16     func_idx;
	u8      cmdq_type;
	u8      rsvd1[1];
	u8      ppf_idx;

	u8      rsvd2[4];

+34 −89
Original line number Diff line number Diff line
@@ -15,7 +15,9 @@
#include <linux/jiffies.h>
#include <linux/log2.h>
#include <linux/err.h>
#include <linux/netdevice.h>

#include "hinic_sriov.h"
#include "hinic_hw_if.h"
#include "hinic_hw_eqs.h"
#include "hinic_hw_mgmt.h"
@@ -46,20 +48,6 @@ enum hw_ioctxt_set_cmdq_depth {
	HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT,
};

/* HW struct */
struct hinic_dev_cap {
	u8      status;
	u8      version;
	u8      rsvd0[6];

	u8      rsvd1[5];
	u8      intr_type;
	u8      rsvd2[66];
	u16     max_sqs;
	u16     max_rqs;
	u8      rsvd3[208];
};

/**
 * get_capability - convert device capabilities to NIC capabilities
 * @hwdev: the HW device to set and convert device capabilities for
@@ -67,16 +55,13 @@ struct hinic_dev_cap {
 *
 * Return 0 - Success, negative - Failure
 **/
static int get_capability(struct hinic_hwdev *hwdev,
static int parse_capability(struct hinic_hwdev *hwdev,
			    struct hinic_dev_cap *dev_cap)
{
	struct hinic_cap *nic_cap = &hwdev->nic_cap;
	int num_aeqs, num_ceqs, num_irqs;

	if (!HINIC_IS_PF(hwdev->hwif) && !HINIC_IS_PPF(hwdev->hwif))
		return -EINVAL;

	if (dev_cap->intr_type != INTR_MSIX_TYPE)
	if (!HINIC_IS_VF(hwdev->hwif) && dev_cap->intr_type != INTR_MSIX_TYPE)
		return -EFAULT;

	num_aeqs = HINIC_HWIF_NUM_AEQS(hwdev->hwif);
@@ -89,13 +74,19 @@ static int get_capability(struct hinic_hwdev *hwdev,
	if (nic_cap->num_qps > HINIC_Q_CTXT_MAX)
		nic_cap->num_qps = HINIC_Q_CTXT_MAX;

	if (!HINIC_IS_VF(hwdev->hwif))
		nic_cap->max_qps = dev_cap->max_sqs + 1;
	if (nic_cap->max_qps != (dev_cap->max_rqs + 1))
		return -EFAULT;
	else
		nic_cap->max_qps = dev_cap->max_sqs;

	if (nic_cap->num_qps > nic_cap->max_qps)
		nic_cap->num_qps = nic_cap->max_qps;

	if (!HINIC_IS_VF(hwdev->hwif)) {
		nic_cap->max_vf = dev_cap->max_vf;
		nic_cap->max_vf_qps = dev_cap->max_vf_sqs + 1;
	}

	return 0;
}

@@ -105,27 +96,26 @@ static int get_capability(struct hinic_hwdev *hwdev,
 *
 * Return 0 - Success, negative - Failure
 **/
static int get_cap_from_fw(struct hinic_pfhwdev *pfhwdev)
static int get_capability(struct hinic_pfhwdev *pfhwdev)
{
	struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
	struct hinic_hwif *hwif = hwdev->hwif;
	struct pci_dev *pdev = hwif->pdev;
	struct hinic_dev_cap dev_cap;
	u16 in_len, out_len;
	u16 out_len;
	int err;

	in_len = 0;
	out_len = sizeof(dev_cap);

	err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_CFGM,
				HINIC_CFG_NIC_CAP, &dev_cap, in_len, &dev_cap,
				&out_len, HINIC_MGMT_MSG_SYNC);
				HINIC_CFG_NIC_CAP, &dev_cap, sizeof(dev_cap),
				&dev_cap, &out_len, HINIC_MGMT_MSG_SYNC);
	if (err) {
		dev_err(&pdev->dev, "Failed to get capability from FW\n");
		return err;
	}

	return get_capability(hwdev, &dev_cap);
	return parse_capability(hwdev, &dev_cap);
}

/**
@@ -144,15 +134,14 @@ static int get_dev_cap(struct hinic_hwdev *hwdev)
	switch (HINIC_FUNC_TYPE(hwif)) {
	case HINIC_PPF:
	case HINIC_PF:
	case HINIC_VF:
		pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);

		err = get_cap_from_fw(pfhwdev);
		err = get_capability(pfhwdev);
		if (err) {
			dev_err(&pdev->dev, "Failed to get capability from FW\n");
			dev_err(&pdev->dev, "Failed to get capability\n");
			return err;
		}
		break;

	default:
		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
		return -EINVAL;
@@ -225,15 +214,8 @@ static void disable_msix(struct hinic_hwdev *hwdev)
int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd,
		       void *buf_in, u16 in_size, void *buf_out, u16 *out_size)
{
	struct hinic_hwif *hwif = hwdev->hwif;
	struct pci_dev *pdev = hwif->pdev;
	struct hinic_pfhwdev *pfhwdev;

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "unsupported PCI Function type\n");
		return -EINVAL;
	}

	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);

	return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC, cmd,
@@ -252,14 +234,9 @@ static int init_fw_ctxt(struct hinic_hwdev *hwdev)
	struct hinic_hwif *hwif = hwdev->hwif;
	struct pci_dev *pdev = hwif->pdev;
	struct hinic_cmd_fw_ctxt fw_ctxt;
	u16 out_size;
	u16 out_size = sizeof(fw_ctxt);
	int err;

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
		return -EINVAL;
	}

	fw_ctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
	fw_ctxt.rx_buf_sz = HINIC_RX_BUF_SZ;

@@ -288,14 +265,8 @@ static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int rq_depth,
{
	struct hinic_hwif *hwif = hwdev->hwif;
	struct hinic_cmd_hw_ioctxt hw_ioctxt;
	struct pci_dev *pdev = hwif->pdev;
	struct hinic_pfhwdev *pfhwdev;

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
		return -EINVAL;
	}

	hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
	hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwif);

@@ -374,11 +345,6 @@ static int clear_io_resources(struct hinic_hwdev *hwdev)
	struct hinic_pfhwdev *pfhwdev;
	int err;

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
		return -EINVAL;
	}

	/* sleep 100ms to wait for firmware stopping I/O */
	msleep(100);

@@ -410,14 +376,8 @@ static int set_resources_state(struct hinic_hwdev *hwdev,
{
	struct hinic_cmd_set_res_state res_state;
	struct hinic_hwif *hwif = hwdev->hwif;
	struct pci_dev *pdev = hwif->pdev;
	struct hinic_pfhwdev *pfhwdev;

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
		return -EINVAL;
	}

	res_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
	res_state.state = state;

@@ -441,8 +401,8 @@ static int get_base_qpn(struct hinic_hwdev *hwdev, u16 *base_qpn)
{
	struct hinic_cmd_base_qpn cmd_base_qpn;
	struct hinic_hwif *hwif = hwdev->hwif;
	u16 out_size = sizeof(cmd_base_qpn);
	struct pci_dev *pdev = hwif->pdev;
	u16 out_size;
	int err;

	cmd_base_qpn.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
@@ -488,7 +448,7 @@ int hinic_hwdev_ifup(struct hinic_hwdev *hwdev)
	num_ceqs = HINIC_HWIF_NUM_CEQS(hwif);

	ceq_msix_entries = &hwdev->msix_entries[num_aeqs];

	func_to_io->hwdev = hwdev;
	err = hinic_io_init(func_to_io, hwif, nic_cap->max_qps, num_ceqs,
			    ceq_msix_entries);
	if (err) {
@@ -558,17 +518,10 @@ void hinic_hwdev_cb_register(struct hinic_hwdev *hwdev,
					     u16 in_size, void *buf_out,
					     u16 *out_size))
{
	struct hinic_hwif *hwif = hwdev->hwif;
	struct pci_dev *pdev = hwif->pdev;
	struct hinic_pfhwdev *pfhwdev;
	struct hinic_nic_cb *nic_cb;
	u8 cmd_cb;

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "unsupported PCI Function type\n");
		return;
	}

	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);

	cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE;
@@ -588,15 +541,12 @@ void hinic_hwdev_cb_unregister(struct hinic_hwdev *hwdev,
			       enum hinic_mgmt_msg_cmd cmd)
{
	struct hinic_hwif *hwif = hwdev->hwif;
	struct pci_dev *pdev = hwif->pdev;
	struct hinic_pfhwdev *pfhwdev;
	struct hinic_nic_cb *nic_cb;
	u8 cmd_cb;

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "unsupported PCI Function type\n");
	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif))
		return;
	}

	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);

@@ -742,12 +692,6 @@ struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)
		return ERR_PTR(err);
	}

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
		err = -EFAULT;
		goto err_func_type;
	}

	pfhwdev = devm_kzalloc(&pdev->dev, sizeof(*pfhwdev), GFP_KERNEL);
	if (!pfhwdev) {
		err = -ENOMEM;
@@ -791,6 +735,12 @@ struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)
		goto err_dev_cap;
	}

	err = hinic_vf_func_init(hwdev);
	if (err) {
		dev_err(&pdev->dev, "Failed to init nic mbox\n");
		goto err_vf_func_init;
	}

	err = init_fw_ctxt(hwdev);
	if (err) {
		dev_err(&pdev->dev, "Failed to init function table\n");
@@ -807,6 +757,8 @@ struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)

err_resources_state:
err_init_fw_ctxt:
	hinic_vf_func_free(hwdev);
err_vf_func_init:
err_dev_cap:
	free_pfhwdev(pfhwdev);

@@ -818,7 +770,6 @@ err_aeqs_init:

err_init_msix:
err_pfhwdev_alloc:
err_func_type:
	hinic_free_hwif(hwif);
	return ERR_PTR(err);
}
@@ -949,15 +900,9 @@ int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq,
{
	struct hinic_qp *qp = container_of(sq, struct hinic_qp, sq);
	struct hinic_hwif *hwif = hwdev->hwif;
	struct pci_dev *pdev = hwif->pdev;
	struct hinic_pfhwdev *pfhwdev;
	struct hinic_cmd_hw_ci hw_ci;

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
		return -EINVAL;
	}

	hw_ci.dma_attr_off  = 0;
	hw_ci.pending_limit = pending_limit;
	hw_ci.coalesc_timer = coalesc_timer;
Loading