Skip to content

Commit 19d8e8c

Browse files
SruChallaherbertx
authored andcommitted
crypto: octeontx2 - add virtual function driver support
Add support for the Marvell OcteonTX2 CPT virtual function driver. This patch includes probe, PCI specific initialization and interrupt handling. Signed-off-by: Suheil Chandran <schandran@marvell.com> Signed-off-by: Lukasz Bartosik <lbartosik@marvell.com> Signed-off-by: Srujana Challa <schalla@marvell.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 78506c2 commit 19d8e8c

File tree

6 files changed

+373
-1
lines changed

6 files changed

+373
-1
lines changed
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# SPDX-License-Identifier: GPL-2.0-only
2-
obj-$(CONFIG_CRYPTO_DEV_OCTEONTX2_CPT) += octeontx2-cpt.o
2+
obj-$(CONFIG_CRYPTO_DEV_OCTEONTX2_CPT) += octeontx2-cpt.o octeontx2-cptvf.o
33

44
octeontx2-cpt-objs := otx2_cptpf_main.o otx2_cptpf_mbox.o \
55
otx2_cpt_mbox_common.o otx2_cptpf_ucode.o otx2_cptlf.o
6+
octeontx2-cptvf-objs := otx2_cptvf_main.o otx2_cptvf_mbox.o otx2_cptlf.o \
7+
otx2_cpt_mbox_common.o
68

79
ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af

drivers/crypto/marvell/octeontx2/otx2_cpt_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,6 @@ int otx2_cpt_write_af_reg(struct otx2_mbox *mbox, struct pci_dev *pdev,
115115
struct otx2_cptlfs_info;
116116
int otx2_cpt_attach_rscrs_msg(struct otx2_cptlfs_info *lfs);
117117
int otx2_cpt_detach_rsrcs_msg(struct otx2_cptlfs_info *lfs);
118+
int otx2_cpt_msix_offset_msg(struct otx2_cptlfs_info *lfs);
118119

119120
#endif /* __OTX2_CPT_COMMON_H */

drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,35 @@ int otx2_cpt_detach_rsrcs_msg(struct otx2_cptlfs_info *lfs)
168168

169169
return ret;
170170
}
171+
172+
int otx2_cpt_msix_offset_msg(struct otx2_cptlfs_info *lfs)
173+
{
174+
struct otx2_mbox *mbox = lfs->mbox;
175+
struct pci_dev *pdev = lfs->pdev;
176+
struct mbox_msghdr *req;
177+
int ret, i;
178+
179+
req = otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req),
180+
sizeof(struct msix_offset_rsp));
181+
if (req == NULL) {
182+
dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");
183+
return -EFAULT;
184+
}
185+
186+
req->id = MBOX_MSG_MSIX_OFFSET;
187+
req->sig = OTX2_MBOX_REQ_SIG;
188+
req->pcifunc = 0;
189+
ret = otx2_cpt_send_mbox_msg(mbox, pdev);
190+
if (ret)
191+
return ret;
192+
193+
for (i = 0; i < lfs->lfs_num; i++) {
194+
if (lfs->lf[i].msix_offset == MSIX_VECTOR_INVALID) {
195+
dev_err(&pdev->dev,
196+
"Invalid msix offset %d for LF %d\n",
197+
lfs->lf[i].msix_offset, i);
198+
return -EINVAL;
199+
}
200+
}
201+
return ret;
202+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only
2+
* Copyright (C) 2020 Marvell.
3+
*/
4+
5+
#ifndef __OTX2_CPTVF_H
6+
#define __OTX2_CPTVF_H
7+
8+
#include "mbox.h"
9+
#include "otx2_cptlf.h"
10+
11+
struct otx2_cptvf_dev {
12+
void __iomem *reg_base; /* Register start address */
13+
void __iomem *pfvf_mbox_base; /* PF-VF mbox start address */
14+
struct pci_dev *pdev; /* PCI device handle */
15+
struct otx2_cptlfs_info lfs; /* CPT LFs attached to this VF */
16+
u8 vf_id; /* Virtual function index */
17+
18+
/* PF <=> VF mbox */
19+
struct otx2_mbox pfvf_mbox;
20+
struct work_struct pfvf_mbox_work;
21+
struct workqueue_struct *pfvf_mbox_wq;
22+
};
23+
24+
irqreturn_t otx2_cptvf_pfvf_mbox_intr(int irq, void *arg);
25+
void otx2_cptvf_pfvf_mbox_handler(struct work_struct *work);
26+
int otx2_cptvf_send_eng_grp_num_msg(struct otx2_cptvf_dev *cptvf, int eng_type);
27+
28+
#endif /* __OTX2_CPTVF_H */
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright (C) 2020 Marvell. */
3+
4+
#include "otx2_cpt_common.h"
5+
#include "otx2_cptvf.h"
6+
#include <rvu_reg.h>
7+
8+
#define OTX2_CPTVF_DRV_NAME "octeontx2-cptvf"
9+
10+
static void cptvf_enable_pfvf_mbox_intrs(struct otx2_cptvf_dev *cptvf)
11+
{
12+
/* Clear interrupt if any */
13+
otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0, OTX2_RVU_VF_INT,
14+
0x1ULL);
15+
16+
/* Enable PF-VF interrupt */
17+
otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0,
18+
OTX2_RVU_VF_INT_ENA_W1S, 0x1ULL);
19+
}
20+
21+
static void cptvf_disable_pfvf_mbox_intrs(struct otx2_cptvf_dev *cptvf)
22+
{
23+
/* Disable PF-VF interrupt */
24+
otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0,
25+
OTX2_RVU_VF_INT_ENA_W1C, 0x1ULL);
26+
27+
/* Clear interrupt if any */
28+
otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0, OTX2_RVU_VF_INT,
29+
0x1ULL);
30+
}
31+
32+
static int cptvf_register_interrupts(struct otx2_cptvf_dev *cptvf)
33+
{
34+
int ret, irq;
35+
u32 num_vec;
36+
37+
num_vec = pci_msix_vec_count(cptvf->pdev);
38+
if (num_vec <= 0)
39+
return -EINVAL;
40+
41+
/* Enable MSI-X */
42+
ret = pci_alloc_irq_vectors(cptvf->pdev, num_vec, num_vec,
43+
PCI_IRQ_MSIX);
44+
if (ret < 0) {
45+
dev_err(&cptvf->pdev->dev,
46+
"Request for %d msix vectors failed\n", num_vec);
47+
return ret;
48+
}
49+
irq = pci_irq_vector(cptvf->pdev, OTX2_CPT_VF_INT_VEC_E_MBOX);
50+
/* Register VF<=>PF mailbox interrupt handler */
51+
ret = devm_request_irq(&cptvf->pdev->dev, irq,
52+
otx2_cptvf_pfvf_mbox_intr, 0,
53+
"CPTPFVF Mbox", cptvf);
54+
if (ret)
55+
return ret;
56+
/* Enable PF-VF mailbox interrupts */
57+
cptvf_enable_pfvf_mbox_intrs(cptvf);
58+
59+
ret = otx2_cpt_send_ready_msg(&cptvf->pfvf_mbox, cptvf->pdev);
60+
if (ret) {
61+
dev_warn(&cptvf->pdev->dev,
62+
"PF not responding to mailbox, deferring probe\n");
63+
cptvf_disable_pfvf_mbox_intrs(cptvf);
64+
return -EPROBE_DEFER;
65+
}
66+
return 0;
67+
}
68+
69+
static int cptvf_pfvf_mbox_init(struct otx2_cptvf_dev *cptvf)
70+
{
71+
int ret;
72+
73+
cptvf->pfvf_mbox_wq = alloc_workqueue("cpt_pfvf_mailbox",
74+
WQ_UNBOUND | WQ_HIGHPRI |
75+
WQ_MEM_RECLAIM, 1);
76+
if (!cptvf->pfvf_mbox_wq)
77+
return -ENOMEM;
78+
79+
ret = otx2_mbox_init(&cptvf->pfvf_mbox, cptvf->pfvf_mbox_base,
80+
cptvf->pdev, cptvf->reg_base, MBOX_DIR_VFPF, 1);
81+
if (ret)
82+
goto free_wqe;
83+
84+
INIT_WORK(&cptvf->pfvf_mbox_work, otx2_cptvf_pfvf_mbox_handler);
85+
return 0;
86+
87+
free_wqe:
88+
destroy_workqueue(cptvf->pfvf_mbox_wq);
89+
return ret;
90+
}
91+
92+
static void cptvf_pfvf_mbox_destroy(struct otx2_cptvf_dev *cptvf)
93+
{
94+
destroy_workqueue(cptvf->pfvf_mbox_wq);
95+
otx2_mbox_destroy(&cptvf->pfvf_mbox);
96+
}
97+
98+
static int otx2_cptvf_probe(struct pci_dev *pdev,
99+
const struct pci_device_id *ent)
100+
{
101+
struct device *dev = &pdev->dev;
102+
resource_size_t offset, size;
103+
struct otx2_cptvf_dev *cptvf;
104+
int ret;
105+
106+
cptvf = devm_kzalloc(dev, sizeof(*cptvf), GFP_KERNEL);
107+
if (!cptvf)
108+
return -ENOMEM;
109+
110+
ret = pcim_enable_device(pdev);
111+
if (ret) {
112+
dev_err(dev, "Failed to enable PCI device\n");
113+
goto clear_drvdata;
114+
}
115+
116+
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
117+
if (ret) {
118+
dev_err(dev, "Unable to get usable DMA configuration\n");
119+
goto clear_drvdata;
120+
}
121+
/* Map VF's configuration registers */
122+
ret = pcim_iomap_regions_request_all(pdev, 1 << PCI_PF_REG_BAR_NUM,
123+
OTX2_CPTVF_DRV_NAME);
124+
if (ret) {
125+
dev_err(dev, "Couldn't get PCI resources 0x%x\n", ret);
126+
goto clear_drvdata;
127+
}
128+
pci_set_master(pdev);
129+
pci_set_drvdata(pdev, cptvf);
130+
cptvf->pdev = pdev;
131+
132+
cptvf->reg_base = pcim_iomap_table(pdev)[PCI_PF_REG_BAR_NUM];
133+
134+
offset = pci_resource_start(pdev, PCI_MBOX_BAR_NUM);
135+
size = pci_resource_len(pdev, PCI_MBOX_BAR_NUM);
136+
/* Map PF-VF mailbox memory */
137+
cptvf->pfvf_mbox_base = devm_ioremap_wc(dev, offset, size);
138+
if (!cptvf->pfvf_mbox_base) {
139+
dev_err(&pdev->dev, "Unable to map BAR4\n");
140+
ret = -ENODEV;
141+
goto clear_drvdata;
142+
}
143+
/* Initialize PF<=>VF mailbox */
144+
ret = cptvf_pfvf_mbox_init(cptvf);
145+
if (ret)
146+
goto clear_drvdata;
147+
148+
/* Register interrupts */
149+
ret = cptvf_register_interrupts(cptvf);
150+
if (ret)
151+
goto destroy_pfvf_mbox;
152+
153+
return 0;
154+
155+
destroy_pfvf_mbox:
156+
cptvf_pfvf_mbox_destroy(cptvf);
157+
clear_drvdata:
158+
pci_set_drvdata(pdev, NULL);
159+
160+
return ret;
161+
}
162+
163+
static void otx2_cptvf_remove(struct pci_dev *pdev)
164+
{
165+
struct otx2_cptvf_dev *cptvf = pci_get_drvdata(pdev);
166+
167+
if (!cptvf) {
168+
dev_err(&pdev->dev, "Invalid CPT VF device.\n");
169+
return;
170+
}
171+
/* Disable PF-VF mailbox interrupt */
172+
cptvf_disable_pfvf_mbox_intrs(cptvf);
173+
/* Destroy PF-VF mbox */
174+
cptvf_pfvf_mbox_destroy(cptvf);
175+
pci_set_drvdata(pdev, NULL);
176+
}
177+
178+
/* Supported devices */
179+
static const struct pci_device_id otx2_cptvf_id_table[] = {
180+
{PCI_VDEVICE(CAVIUM, OTX2_CPT_PCI_VF_DEVICE_ID), 0},
181+
{ 0, } /* end of table */
182+
};
183+
184+
static struct pci_driver otx2_cptvf_pci_driver = {
185+
.name = OTX2_CPTVF_DRV_NAME,
186+
.id_table = otx2_cptvf_id_table,
187+
.probe = otx2_cptvf_probe,
188+
.remove = otx2_cptvf_remove,
189+
};
190+
191+
module_pci_driver(otx2_cptvf_pci_driver);
192+
193+
MODULE_AUTHOR("Marvell");
194+
MODULE_DESCRIPTION("Marvell OcteonTX2 CPT Virtual Function Driver");
195+
MODULE_LICENSE("GPL v2");
196+
MODULE_DEVICE_TABLE(pci, otx2_cptvf_id_table);
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright (C) 2020 Marvell. */
3+
4+
#include "otx2_cpt_common.h"
5+
#include "otx2_cptvf.h"
6+
#include <rvu_reg.h>
7+
8+
irqreturn_t otx2_cptvf_pfvf_mbox_intr(int __always_unused irq, void *arg)
9+
{
10+
struct otx2_cptvf_dev *cptvf = arg;
11+
u64 intr;
12+
13+
/* Read the interrupt bits */
14+
intr = otx2_cpt_read64(cptvf->reg_base, BLKADDR_RVUM, 0,
15+
OTX2_RVU_VF_INT);
16+
17+
if (intr & 0x1ULL) {
18+
/* Schedule work queue function to process the MBOX request */
19+
queue_work(cptvf->pfvf_mbox_wq, &cptvf->pfvf_mbox_work);
20+
/* Clear and ack the interrupt */
21+
otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0,
22+
OTX2_RVU_VF_INT, 0x1ULL);
23+
}
24+
return IRQ_HANDLED;
25+
}
26+
27+
static void process_pfvf_mbox_mbox_msg(struct otx2_cptvf_dev *cptvf,
28+
struct mbox_msghdr *msg)
29+
{
30+
struct otx2_cptlfs_info *lfs = &cptvf->lfs;
31+
struct cpt_rd_wr_reg_msg *rsp_reg;
32+
struct msix_offset_rsp *rsp_msix;
33+
int i;
34+
35+
if (msg->id >= MBOX_MSG_MAX) {
36+
dev_err(&cptvf->pdev->dev,
37+
"MBOX msg with unknown ID %d\n", msg->id);
38+
return;
39+
}
40+
if (msg->sig != OTX2_MBOX_RSP_SIG) {
41+
dev_err(&cptvf->pdev->dev,
42+
"MBOX msg with wrong signature %x, ID %d\n",
43+
msg->sig, msg->id);
44+
return;
45+
}
46+
switch (msg->id) {
47+
case MBOX_MSG_READY:
48+
cptvf->vf_id = ((msg->pcifunc >> RVU_PFVF_FUNC_SHIFT)
49+
& RVU_PFVF_FUNC_MASK) - 1;
50+
break;
51+
case MBOX_MSG_ATTACH_RESOURCES:
52+
/* Check if resources were successfully attached */
53+
if (!msg->rc)
54+
lfs->are_lfs_attached = 1;
55+
break;
56+
case MBOX_MSG_DETACH_RESOURCES:
57+
/* Check if resources were successfully detached */
58+
if (!msg->rc)
59+
lfs->are_lfs_attached = 0;
60+
break;
61+
case MBOX_MSG_MSIX_OFFSET:
62+
rsp_msix = (struct msix_offset_rsp *) msg;
63+
for (i = 0; i < rsp_msix->cptlfs; i++)
64+
lfs->lf[i].msix_offset = rsp_msix->cptlf_msixoff[i];
65+
break;
66+
case MBOX_MSG_CPT_RD_WR_REGISTER:
67+
rsp_reg = (struct cpt_rd_wr_reg_msg *) msg;
68+
if (msg->rc) {
69+
dev_err(&cptvf->pdev->dev,
70+
"Reg %llx rd/wr(%d) failed %d\n",
71+
rsp_reg->reg_offset, rsp_reg->is_write,
72+
msg->rc);
73+
return;
74+
}
75+
if (!rsp_reg->is_write)
76+
*rsp_reg->ret_val = rsp_reg->val;
77+
break;
78+
default:
79+
dev_err(&cptvf->pdev->dev, "Unsupported msg %d received.\n",
80+
msg->id);
81+
break;
82+
}
83+
}
84+
85+
void otx2_cptvf_pfvf_mbox_handler(struct work_struct *work)
86+
{
87+
struct otx2_cptvf_dev *cptvf;
88+
struct otx2_mbox *pfvf_mbox;
89+
struct otx2_mbox_dev *mdev;
90+
struct mbox_hdr *rsp_hdr;
91+
struct mbox_msghdr *msg;
92+
int offset, i;
93+
94+
/* sync with mbox memory region */
95+
smp_rmb();
96+
97+
cptvf = container_of(work, struct otx2_cptvf_dev, pfvf_mbox_work);
98+
pfvf_mbox = &cptvf->pfvf_mbox;
99+
mdev = &pfvf_mbox->dev[0];
100+
rsp_hdr = (struct mbox_hdr *)(mdev->mbase + pfvf_mbox->rx_start);
101+
if (rsp_hdr->num_msgs == 0)
102+
return;
103+
offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
104+
105+
for (i = 0; i < rsp_hdr->num_msgs; i++) {
106+
msg = (struct mbox_msghdr *)(mdev->mbase + pfvf_mbox->rx_start +
107+
offset);
108+
process_pfvf_mbox_mbox_msg(cptvf, msg);
109+
offset = msg->next_msgoff;
110+
mdev->msgs_acked++;
111+
}
112+
otx2_mbox_reset(pfvf_mbox, 0);
113+
}

0 commit comments

Comments
 (0)