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: Tomasz Duszynski <tduszynski@marvell.com> Signed-off-by: Sunil Goutham <sgoutham@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
05c22b5431
commit
ad513ed938
@ -193,6 +193,12 @@ struct otx2_hw {
|
|||||||
u64 cgx_tx_stats[CGX_TX_STATS_COUNT];
|
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 flr_work {
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
struct otx2_nic *pf;
|
struct otx2_nic *pf;
|
||||||
@ -229,6 +235,7 @@ struct otx2_nic {
|
|||||||
u8 total_vfs;
|
u8 total_vfs;
|
||||||
u16 pcifunc; /* RVU PF_FUNC */
|
u16 pcifunc; /* RVU PF_FUNC */
|
||||||
u16 bpid[NIX_MAX_BPID_CHAN];
|
u16 bpid[NIX_MAX_BPID_CHAN];
|
||||||
|
struct otx2_vf_config *vf_configs;
|
||||||
struct cgx_link_user_info linfo;
|
struct cgx_link_user_info linfo;
|
||||||
|
|
||||||
u64 reset_count;
|
u64 reset_count;
|
||||||
|
@ -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,
|
static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf,
|
||||||
struct mbox_msghdr *msg)
|
struct mbox_msghdr *msg)
|
||||||
{
|
{
|
||||||
|
int devid;
|
||||||
|
|
||||||
if (msg->id >= MBOX_MSG_MAX) {
|
if (msg->id >= MBOX_MSG_MAX) {
|
||||||
dev_err(pf->dev,
|
dev_err(pf->dev,
|
||||||
"Mbox msg with unknown ID 0x%x\n", msg->id);
|
"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;
|
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) {
|
switch (msg->id) {
|
||||||
case MBOX_MSG_READY:
|
case MBOX_MSG_READY:
|
||||||
pf->pcifunc = msg->pcifunc;
|
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 cgx_link_info_msg *msg,
|
||||||
struct msg_rsp *rsp)
|
struct msg_rsp *rsp)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Copy the link info sent by AF */
|
/* Copy the link info sent by AF */
|
||||||
pf->linfo = msg->link_info;
|
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 */
|
/* interface has not been fully configured yet */
|
||||||
if (pf->flags & OTX2_FLAG_INTF_DOWN)
|
if (pf->flags & OTX2_FLAG_INTF_DOWN)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1925,11 +1960,39 @@ err_release_regions:
|
|||||||
return err;
|
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)
|
static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs)
|
||||||
{
|
{
|
||||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||||
struct otx2_nic *pf = netdev_priv(netdev);
|
struct otx2_nic *pf = netdev_priv(netdev);
|
||||||
int ret;
|
int ret, i;
|
||||||
|
|
||||||
/* Init PF <=> VF mailbox stuff */
|
/* Init PF <=> VF mailbox stuff */
|
||||||
ret = otx2_pfvf_mbox_init(pf, numvfs);
|
ret = otx2_pfvf_mbox_init(pf, numvfs);
|
||||||
@ -1940,9 +2003,23 @@ static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto free_mbox;
|
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);
|
ret = otx2_pf_flr_init(pf, numvfs);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto free_intr;
|
goto free_configs;
|
||||||
|
|
||||||
ret = otx2_register_flr_me_intr(pf, numvfs);
|
ret = otx2_register_flr_me_intr(pf, numvfs);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -1957,6 +2034,8 @@ free_flr_intr:
|
|||||||
otx2_disable_flr_me_intr(pf);
|
otx2_disable_flr_me_intr(pf);
|
||||||
free_flr:
|
free_flr:
|
||||||
otx2_flr_wq_destroy(pf);
|
otx2_flr_wq_destroy(pf);
|
||||||
|
free_configs:
|
||||||
|
kfree(pf->vf_configs);
|
||||||
free_intr:
|
free_intr:
|
||||||
otx2_disable_pfvf_mbox_intr(pf, numvfs);
|
otx2_disable_pfvf_mbox_intr(pf, numvfs);
|
||||||
free_mbox:
|
free_mbox:
|
||||||
@ -1969,12 +2048,17 @@ static int otx2_sriov_disable(struct pci_dev *pdev)
|
|||||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||||
struct otx2_nic *pf = netdev_priv(netdev);
|
struct otx2_nic *pf = netdev_priv(netdev);
|
||||||
int numvfs = pci_num_vf(pdev);
|
int numvfs = pci_num_vf(pdev);
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!numvfs)
|
if (!numvfs)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pci_disable_sriov(pdev);
|
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_disable_flr_me_intr(pf);
|
||||||
otx2_flr_wq_destroy(pf);
|
otx2_flr_wq_destroy(pf);
|
||||||
otx2_disable_pfvf_mbox_intr(pf, numvfs);
|
otx2_disable_pfvf_mbox_intr(pf, numvfs);
|
||||||
|
Loading…
Reference in New Issue
Block a user