Commit ad513ed9 authored by Tomasz Duszynski's avatar Tomasz Duszynski Committed by David S. Miller
Browse files

octeontx2-vf: Link event notification support



VF shares physical link with PF. Admin function (AF) sends
notification to PF whenever a link change event happens. PF
has to forward the same notification to each of the enabled VF.

PF traps START/STOP_RX messages sent by VF to AF to keep track of
VF's enabled/disabled state.

Signed-off-by: default avatarTomasz Duszynski <tduszynski@marvell.com>
Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 05c22b54
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -193,6 +193,12 @@ struct otx2_hw {
	u64			cgx_tx_stats[CGX_TX_STATS_COUNT];
};

struct otx2_vf_config {
	struct otx2_nic *pf;
	struct delayed_work link_event_work;
	bool intf_down; /* interface was either configured or not */
};

struct flr_work {
	struct work_struct work;
	struct otx2_nic *pf;
@@ -229,6 +235,7 @@ struct otx2_nic {
	u8			total_vfs;
	u16			pcifunc; /* RVU PF_FUNC */
	u16			bpid[NIX_MAX_BPID_CHAN];
	struct otx2_vf_config	*vf_configs;
	struct cgx_link_user_info linfo;

	u64			reset_count;
+86 −2
Original line number Diff line number Diff line
@@ -715,6 +715,8 @@ static int otx2_register_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs)
static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf,
				       struct mbox_msghdr *msg)
{
	int devid;

	if (msg->id >= MBOX_MSG_MAX) {
		dev_err(pf->dev,
			"Mbox msg with unknown ID 0x%x\n", msg->id);
@@ -728,6 +730,26 @@ static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf,
		return;
	}

	/* message response heading VF */
	devid = msg->pcifunc & RVU_PFVF_FUNC_MASK;
	if (devid) {
		struct otx2_vf_config *config = &pf->vf_configs[devid - 1];
		struct delayed_work *dwork;

		switch (msg->id) {
		case MBOX_MSG_NIX_LF_START_RX:
			config->intf_down = false;
			dwork = &config->link_event_work;
			schedule_delayed_work(dwork, msecs_to_jiffies(100));
			break;
		case MBOX_MSG_NIX_LF_STOP_RX:
			config->intf_down = true;
			break;
		}

		return;
	}

	switch (msg->id) {
	case MBOX_MSG_READY:
		pf->pcifunc = msg->pcifunc;
@@ -809,9 +831,22 @@ int otx2_mbox_up_handler_cgx_link_event(struct otx2_nic *pf,
					struct cgx_link_info_msg *msg,
					struct msg_rsp *rsp)
{
	int i;

	/* Copy the link info sent by AF */
	pf->linfo = msg->link_info;

	/* notify VFs about link event */
	for (i = 0; i < pci_num_vf(pf->pdev); i++) {
		struct otx2_vf_config *config = &pf->vf_configs[i];
		struct delayed_work *dwork = &config->link_event_work;

		if (config->intf_down)
			continue;

		schedule_delayed_work(dwork, msecs_to_jiffies(100));
	}

	/* interface has not been fully configured yet */
	if (pf->flags & OTX2_FLAG_INTF_DOWN)
		return 0;
@@ -1925,11 +1960,39 @@ err_release_regions:
	return err;
}

static void otx2_vf_link_event_task(struct work_struct *work)
{
	struct otx2_vf_config *config;
	struct cgx_link_info_msg *req;
	struct mbox_msghdr *msghdr;
	struct otx2_nic *pf;
	int vf_idx;

	config = container_of(work, struct otx2_vf_config,
			      link_event_work.work);
	vf_idx = config - config->pf->vf_configs;
	pf = config->pf;

	msghdr = otx2_mbox_alloc_msg_rsp(&pf->mbox_pfvf[0].mbox_up, vf_idx,
					 sizeof(*req), sizeof(struct msg_rsp));
	if (!msghdr) {
		dev_err(pf->dev, "Failed to create VF%d link event\n", vf_idx);
		return;
	}

	req = (struct cgx_link_info_msg *)msghdr;
	req->hdr.id = MBOX_MSG_CGX_LINK_EVENT;
	req->hdr.sig = OTX2_MBOX_REQ_SIG;
	memcpy(&req->link_info, &pf->linfo, sizeof(req->link_info));

	otx2_sync_mbox_up_msg(&pf->mbox_pfvf[0], vf_idx);
}

static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs)
{
	struct net_device *netdev = pci_get_drvdata(pdev);
	struct otx2_nic *pf = netdev_priv(netdev);
	int ret;
	int ret, i;

	/* Init PF <=> VF mailbox stuff */
	ret = otx2_pfvf_mbox_init(pf, numvfs);
@@ -1940,9 +2003,23 @@ static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs)
	if (ret)
		goto free_mbox;

	pf->vf_configs = kcalloc(numvfs, sizeof(struct otx2_vf_config),
				 GFP_KERNEL);
	if (!pf->vf_configs) {
		ret = -ENOMEM;
		goto free_intr;
	}

	for (i = 0; i < numvfs; i++) {
		pf->vf_configs[i].pf = pf;
		pf->vf_configs[i].intf_down = true;
		INIT_DELAYED_WORK(&pf->vf_configs[i].link_event_work,
				  otx2_vf_link_event_task);
	}

	ret = otx2_pf_flr_init(pf, numvfs);
	if (ret)
		goto free_intr;
		goto free_configs;

	ret = otx2_register_flr_me_intr(pf, numvfs);
	if (ret)
@@ -1957,6 +2034,8 @@ free_flr_intr:
	otx2_disable_flr_me_intr(pf);
free_flr:
	otx2_flr_wq_destroy(pf);
free_configs:
	kfree(pf->vf_configs);
free_intr:
	otx2_disable_pfvf_mbox_intr(pf, numvfs);
free_mbox:
@@ -1969,12 +2048,17 @@ static int otx2_sriov_disable(struct pci_dev *pdev)
	struct net_device *netdev = pci_get_drvdata(pdev);
	struct otx2_nic *pf = netdev_priv(netdev);
	int numvfs = pci_num_vf(pdev);
	int i;

	if (!numvfs)
		return 0;

	pci_disable_sriov(pdev);

	for (i = 0; i < pci_num_vf(pdev); i++)
		cancel_delayed_work_sync(&pf->vf_configs[i].link_event_work);
	kfree(pf->vf_configs);

	otx2_disable_flr_me_intr(pf);
	otx2_flr_wq_destroy(pf);
	otx2_disable_pfvf_mbox_intr(pf, numvfs);