Commit 3184fb5b authored by Tomasz Duszynski's avatar Tomasz Duszynski Committed by David S. Miller

octeontx2-vf: Virtual function driver support

On OcteonTx2 silicon there two two types VFs, VFs that share the
physical link with their parent SR-IOV PF and the VFs which work
in pairs using internal HW loopback channels (LBK). Except for the
underlying Rx/Tx channel mapping from netdev functionality perspective
they are almost identical. This patch adds netdev driver support
for these VFs.

Unlike it's parent PF a VF cannot directly communicate with admin
function (AF) and it has to go through PF for the same. The mailbox
communication with AF works like 'VF <=> PF <=> AF'.

Also functionality wise VF and PF are identical, hence to avoid code
duplication PF driver's APIs are resued here for HW initialization,
packet handling etc etc ie almost everything. For VF driver to compile
as module exported few of the existing PF driver APIs.
Signed-off-by: default avatarSubbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: default avatarGeetha sowjanya <gakula@marvell.com>
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 547d20f1
...@@ -33,3 +33,9 @@ config OCTEONTX2_PF ...@@ -33,3 +33,9 @@ config OCTEONTX2_PF
depends on PCI depends on PCI
help help
This driver supports Marvell's OcteonTX2 NIC physical function. This driver supports Marvell's OcteonTX2 NIC physical function.
config OCTEONTX2_VF
tristate "Marvell OcteonTX2 NIC Virtual Function driver"
depends on OCTEONTX2_PF
help
This driver supports Marvell's OcteonTX2 NIC virtual function.
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
# #
obj-$(CONFIG_OCTEONTX2_PF) += octeontx2_nicpf.o obj-$(CONFIG_OCTEONTX2_PF) += octeontx2_nicpf.o
obj-$(CONFIG_OCTEONTX2_VF) += octeontx2_nicvf.o
octeontx2_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o octeontx2_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o
octeontx2_nicvf-y := otx2_vf.o
ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af
...@@ -128,6 +128,7 @@ void otx2_get_stats64(struct net_device *netdev, ...@@ -128,6 +128,7 @@ void otx2_get_stats64(struct net_device *netdev,
stats->tx_packets = dev_stats->tx_frames; stats->tx_packets = dev_stats->tx_frames;
stats->tx_dropped = dev_stats->tx_drops; stats->tx_dropped = dev_stats->tx_drops;
} }
EXPORT_SYMBOL(otx2_get_stats64);
/* Sync MAC address with RVU AF */ /* Sync MAC address with RVU AF */
static int otx2_hw_set_mac_addr(struct otx2_nic *pfvf, u8 *mac) static int otx2_hw_set_mac_addr(struct otx2_nic *pfvf, u8 *mac)
...@@ -197,6 +198,7 @@ int otx2_set_mac_address(struct net_device *netdev, void *p) ...@@ -197,6 +198,7 @@ int otx2_set_mac_address(struct net_device *netdev, void *p)
return 0; return 0;
} }
EXPORT_SYMBOL(otx2_set_mac_address);
int otx2_hw_set_mtu(struct otx2_nic *pfvf, int mtu) int otx2_hw_set_mtu(struct otx2_nic *pfvf, int mtu)
{ {
...@@ -225,6 +227,9 @@ int otx2_config_pause_frm(struct otx2_nic *pfvf) ...@@ -225,6 +227,9 @@ int otx2_config_pause_frm(struct otx2_nic *pfvf)
struct cgx_pause_frm_cfg *req; struct cgx_pause_frm_cfg *req;
int err; int err;
if (is_otx2_lbkvf(pfvf->pdev))
return 0;
otx2_mbox_lock(&pfvf->mbox); otx2_mbox_lock(&pfvf->mbox);
req = otx2_mbox_alloc_msg_cgx_cfg_pause_frm(&pfvf->mbox); req = otx2_mbox_alloc_msg_cgx_cfg_pause_frm(&pfvf->mbox);
if (!req) { if (!req) {
...@@ -416,6 +421,7 @@ void otx2_tx_timeout(struct net_device *netdev, unsigned int txq) ...@@ -416,6 +421,7 @@ void otx2_tx_timeout(struct net_device *netdev, unsigned int txq)
schedule_work(&pfvf->reset_task); schedule_work(&pfvf->reset_task);
} }
EXPORT_SYMBOL(otx2_tx_timeout);
void otx2_get_mac_from_af(struct net_device *netdev) void otx2_get_mac_from_af(struct net_device *netdev)
{ {
...@@ -430,6 +436,7 @@ void otx2_get_mac_from_af(struct net_device *netdev) ...@@ -430,6 +436,7 @@ void otx2_get_mac_from_af(struct net_device *netdev)
if (!is_valid_ether_addr(netdev->dev_addr)) if (!is_valid_ether_addr(netdev->dev_addr))
eth_hw_addr_random(netdev); eth_hw_addr_random(netdev);
} }
EXPORT_SYMBOL(otx2_get_mac_from_af);
static int otx2_get_link(struct otx2_nic *pfvf) static int otx2_get_link(struct otx2_nic *pfvf)
{ {
...@@ -1263,6 +1270,7 @@ int otx2_detach_resources(struct mbox *mbox) ...@@ -1263,6 +1270,7 @@ int otx2_detach_resources(struct mbox *mbox)
otx2_mbox_unlock(mbox); otx2_mbox_unlock(mbox);
return 0; return 0;
} }
EXPORT_SYMBOL(otx2_detach_resources);
int otx2_attach_npa_nix(struct otx2_nic *pfvf) int otx2_attach_npa_nix(struct otx2_nic *pfvf)
{ {
...@@ -1319,6 +1327,7 @@ int otx2_attach_npa_nix(struct otx2_nic *pfvf) ...@@ -1319,6 +1327,7 @@ int otx2_attach_npa_nix(struct otx2_nic *pfvf)
return 0; return 0;
} }
EXPORT_SYMBOL(otx2_attach_npa_nix);
void otx2_ctx_disable(struct mbox *mbox, int type, bool npa) void otx2_ctx_disable(struct mbox *mbox, int type, bool npa)
{ {
...@@ -1387,6 +1396,7 @@ void mbox_handler_nix_txsch_alloc(struct otx2_nic *pf, ...@@ -1387,6 +1396,7 @@ void mbox_handler_nix_txsch_alloc(struct otx2_nic *pf,
pf->hw.txschq_list[lvl][schq] = pf->hw.txschq_list[lvl][schq] =
rsp->schq_list[lvl][schq]; rsp->schq_list[lvl][schq];
} }
EXPORT_SYMBOL(mbox_handler_nix_txsch_alloc);
void mbox_handler_npa_lf_alloc(struct otx2_nic *pfvf, void mbox_handler_npa_lf_alloc(struct otx2_nic *pfvf,
struct npa_lf_alloc_rsp *rsp) struct npa_lf_alloc_rsp *rsp)
...@@ -1394,6 +1404,7 @@ void mbox_handler_npa_lf_alloc(struct otx2_nic *pfvf, ...@@ -1394,6 +1404,7 @@ void mbox_handler_npa_lf_alloc(struct otx2_nic *pfvf,
pfvf->hw.stack_pg_ptrs = rsp->stack_pg_ptrs; pfvf->hw.stack_pg_ptrs = rsp->stack_pg_ptrs;
pfvf->hw.stack_pg_bytes = rsp->stack_pg_bytes; pfvf->hw.stack_pg_bytes = rsp->stack_pg_bytes;
} }
EXPORT_SYMBOL(mbox_handler_npa_lf_alloc);
void mbox_handler_nix_lf_alloc(struct otx2_nic *pfvf, void mbox_handler_nix_lf_alloc(struct otx2_nic *pfvf,
struct nix_lf_alloc_rsp *rsp) struct nix_lf_alloc_rsp *rsp)
...@@ -1404,6 +1415,7 @@ void mbox_handler_nix_lf_alloc(struct otx2_nic *pfvf, ...@@ -1404,6 +1415,7 @@ void mbox_handler_nix_lf_alloc(struct otx2_nic *pfvf,
pfvf->hw.lso_tsov4_idx = rsp->lso_tsov4_idx; pfvf->hw.lso_tsov4_idx = rsp->lso_tsov4_idx;
pfvf->hw.lso_tsov6_idx = rsp->lso_tsov6_idx; pfvf->hw.lso_tsov6_idx = rsp->lso_tsov6_idx;
} }
EXPORT_SYMBOL(mbox_handler_nix_lf_alloc);
void mbox_handler_msix_offset(struct otx2_nic *pfvf, void mbox_handler_msix_offset(struct otx2_nic *pfvf,
struct msix_offset_rsp *rsp) struct msix_offset_rsp *rsp)
...@@ -1411,6 +1423,7 @@ void mbox_handler_msix_offset(struct otx2_nic *pfvf, ...@@ -1411,6 +1423,7 @@ void mbox_handler_msix_offset(struct otx2_nic *pfvf,
pfvf->hw.npa_msixoff = rsp->npa_msixoff; pfvf->hw.npa_msixoff = rsp->npa_msixoff;
pfvf->hw.nix_msixoff = rsp->nix_msixoff; pfvf->hw.nix_msixoff = rsp->nix_msixoff;
} }
EXPORT_SYMBOL(mbox_handler_msix_offset);
void mbox_handler_nix_bp_enable(struct otx2_nic *pfvf, void mbox_handler_nix_bp_enable(struct otx2_nic *pfvf,
struct nix_bp_cfg_rsp *rsp) struct nix_bp_cfg_rsp *rsp)
...@@ -1422,6 +1435,7 @@ void mbox_handler_nix_bp_enable(struct otx2_nic *pfvf, ...@@ -1422,6 +1435,7 @@ void mbox_handler_nix_bp_enable(struct otx2_nic *pfvf,
pfvf->bpid[chan_id] = rsp->chan_bpid[chan] & 0x3FF; pfvf->bpid[chan_id] = rsp->chan_bpid[chan] & 0x3FF;
} }
} }
EXPORT_SYMBOL(mbox_handler_nix_bp_enable);
void otx2_free_cints(struct otx2_nic *pfvf, int n) void otx2_free_cints(struct otx2_nic *pfvf, int n)
{ {
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
/* PCI device IDs */ /* PCI device IDs */
#define PCI_DEVID_OCTEONTX2_RVU_PF 0xA063 #define PCI_DEVID_OCTEONTX2_RVU_PF 0xA063
#define PCI_DEVID_OCTEONTX2_RVU_VF 0xA064
#define PCI_DEVID_OCTEONTX2_RVU_AFVF 0xA0F8
#define PCI_SUBSYS_DEVID_96XX_RVU_PFVF 0xB200 #define PCI_SUBSYS_DEVID_96XX_RVU_PFVF 0xB200
...@@ -242,6 +244,11 @@ struct otx2_nic { ...@@ -242,6 +244,11 @@ struct otx2_nic {
int nix_blkaddr; int nix_blkaddr;
}; };
static inline bool is_otx2_lbkvf(struct pci_dev *pdev)
{
return pdev->device == PCI_DEVID_OCTEONTX2_RVU_AFVF;
}
static inline bool is_96xx_A0(struct pci_dev *pdev) static inline bool is_96xx_A0(struct pci_dev *pdev)
{ {
return (pdev->revision == 0x00) && return (pdev->revision == 0x00) &&
......
...@@ -1085,6 +1085,7 @@ int otx2_set_real_num_queues(struct net_device *netdev, ...@@ -1085,6 +1085,7 @@ int otx2_set_real_num_queues(struct net_device *netdev,
"Failed to set no of Rx queues: %d\n", rx_queues); "Failed to set no of Rx queues: %d\n", rx_queues);
return err; return err;
} }
EXPORT_SYMBOL(otx2_set_real_num_queues);
static irqreturn_t otx2_q_intr_handler(int irq, void *data) static irqreturn_t otx2_q_intr_handler(int irq, void *data)
{ {
...@@ -1520,6 +1521,9 @@ int otx2_open(struct net_device *netdev) ...@@ -1520,6 +1521,9 @@ int otx2_open(struct net_device *netdev)
if (pf->linfo.link_up && !(pf->pcifunc & RVU_PFVF_FUNC_MASK)) if (pf->linfo.link_up && !(pf->pcifunc & RVU_PFVF_FUNC_MASK))
otx2_handle_link_event(pf); otx2_handle_link_event(pf);
/* Restore pause frame settings */
otx2_config_pause_frm(pf);
err = otx2_rxtx_enable(pf, true); err = otx2_rxtx_enable(pf, true);
if (err) if (err)
goto err_free_cints; goto err_free_cints;
...@@ -1543,6 +1547,7 @@ int otx2_open(struct net_device *netdev) ...@@ -1543,6 +1547,7 @@ int otx2_open(struct net_device *netdev)
kfree(qset->napi); kfree(qset->napi);
return err; return err;
} }
EXPORT_SYMBOL(otx2_open);
int otx2_stop(struct net_device *netdev) int otx2_stop(struct net_device *netdev)
{ {
...@@ -1603,6 +1608,7 @@ int otx2_stop(struct net_device *netdev) ...@@ -1603,6 +1608,7 @@ int otx2_stop(struct net_device *netdev)
sizeof(*qset) - offsetof(struct otx2_qset, sqe_cnt)); sizeof(*qset) - offsetof(struct otx2_qset, sqe_cnt));
return 0; return 0;
} }
EXPORT_SYMBOL(otx2_stop);
static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev) static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
{ {
...@@ -1731,7 +1737,6 @@ static int otx2_realloc_msix_vectors(struct otx2_nic *pf) ...@@ -1731,7 +1737,6 @@ static int otx2_realloc_msix_vectors(struct otx2_nic *pf)
otx2_disable_mbox_intr(pf); otx2_disable_mbox_intr(pf);
pci_free_irq_vectors(hw->pdev); pci_free_irq_vectors(hw->pdev);
pci_free_irq_vectors(hw->pdev);
err = pci_alloc_irq_vectors(hw->pdev, num_vec, num_vec, PCI_IRQ_MSIX); err = pci_alloc_irq_vectors(hw->pdev, num_vec, num_vec, PCI_IRQ_MSIX);
if (err < 0) { if (err < 0) {
dev_err(pf->dev, "%s: Failed to realloc %d IRQ vectors\n", dev_err(pf->dev, "%s: Failed to realloc %d IRQ vectors\n",
...@@ -1898,6 +1903,10 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1898,6 +1903,10 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Enable link notifications */ /* Enable link notifications */
otx2_cgx_config_linkevents(pf, true); otx2_cgx_config_linkevents(pf, true);
/* Enable pause frames by default */
pf->flags |= OTX2_FLAG_RX_PAUSE_ENABLED;
pf->flags |= OTX2_FLAG_TX_PAUSE_ENABLED;
return 0; return 0;
err_detach_rsrc: err_detach_rsrc:
......
...@@ -45,6 +45,19 @@ ...@@ -45,6 +45,19 @@
#define RVU_PF_MSIX_VECX_CTL(a) (0x008 | (a) << 4) #define RVU_PF_MSIX_VECX_CTL(a) (0x008 | (a) << 4)
#define RVU_PF_MSIX_PBAX(a) (0xF0000 | (a) << 3) #define RVU_PF_MSIX_PBAX(a) (0xF0000 | (a) << 3)
/* RVU VF registers */
#define RVU_VF_VFPF_MBOX0 (0x00000)
#define RVU_VF_VFPF_MBOX1 (0x00008)
#define RVU_VF_VFPF_MBOXX(a) (0x00 | (a) << 3)
#define RVU_VF_INT (0x20)
#define RVU_VF_INT_W1S (0x28)
#define RVU_VF_INT_ENA_W1S (0x30)
#define RVU_VF_INT_ENA_W1C (0x38)
#define RVU_VF_BLOCK_ADDRX_DISC(a) (0x200 | (a) << 3)
#define RVU_VF_MSIX_VECX_ADDR(a) (0x000 | (a) << 4)
#define RVU_VF_MSIX_VECX_CTL(a) (0x008 | (a) << 4)
#define RVU_VF_MSIX_PBAX(a) (0xF0000 | (a) << 3)
#define RVU_FUNC_BLKADDR_SHIFT 20 #define RVU_FUNC_BLKADDR_SHIFT 20
#define RVU_FUNC_BLKADDR_MASK 0x1FULL #define RVU_FUNC_BLKADDR_MASK 0x1FULL
......
...@@ -778,6 +778,7 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq, ...@@ -778,6 +778,7 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq,
return true; return true;
} }
EXPORT_SYMBOL(otx2_sq_append_skb);
void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq) void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
{ {
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment