119d8e8c7SSrujana Challa // SPDX-License-Identifier: GPL-2.0-only
219d8e8c7SSrujana Challa /* Copyright (C) 2020 Marvell. */
319d8e8c7SSrujana Challa
419d8e8c7SSrujana Challa #include "otx2_cpt_common.h"
519d8e8c7SSrujana Challa #include "otx2_cptvf.h"
68ec8015aSSrujana Challa #include "otx2_cptlf.h"
76f03f0e8SSrujana Challa #include "otx2_cptvf_algs.h"
8eb33cd91SSrujana Challa #include "cn10k_cpt.h"
919d8e8c7SSrujana Challa #include <rvu_reg.h>
1019d8e8c7SSrujana Challa
114cd8c315SSrujana Challa #define OTX2_CPTVF_DRV_NAME "rvu_cptvf"
1219d8e8c7SSrujana Challa
cptvf_enable_pfvf_mbox_intrs(struct otx2_cptvf_dev * cptvf)1319d8e8c7SSrujana Challa static void cptvf_enable_pfvf_mbox_intrs(struct otx2_cptvf_dev *cptvf)
1419d8e8c7SSrujana Challa {
1519d8e8c7SSrujana Challa /* Clear interrupt if any */
1619d8e8c7SSrujana Challa otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0, OTX2_RVU_VF_INT,
1719d8e8c7SSrujana Challa 0x1ULL);
1819d8e8c7SSrujana Challa
1919d8e8c7SSrujana Challa /* Enable PF-VF interrupt */
2019d8e8c7SSrujana Challa otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0,
2119d8e8c7SSrujana Challa OTX2_RVU_VF_INT_ENA_W1S, 0x1ULL);
2219d8e8c7SSrujana Challa }
2319d8e8c7SSrujana Challa
cptvf_disable_pfvf_mbox_intrs(struct otx2_cptvf_dev * cptvf)2419d8e8c7SSrujana Challa static void cptvf_disable_pfvf_mbox_intrs(struct otx2_cptvf_dev *cptvf)
2519d8e8c7SSrujana Challa {
2619d8e8c7SSrujana Challa /* Disable PF-VF interrupt */
2719d8e8c7SSrujana Challa otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0,
2819d8e8c7SSrujana Challa OTX2_RVU_VF_INT_ENA_W1C, 0x1ULL);
2919d8e8c7SSrujana Challa
3019d8e8c7SSrujana Challa /* Clear interrupt if any */
3119d8e8c7SSrujana Challa otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0, OTX2_RVU_VF_INT,
3219d8e8c7SSrujana Challa 0x1ULL);
3319d8e8c7SSrujana Challa }
3419d8e8c7SSrujana Challa
cptvf_register_interrupts(struct otx2_cptvf_dev * cptvf)3519d8e8c7SSrujana Challa static int cptvf_register_interrupts(struct otx2_cptvf_dev *cptvf)
3619d8e8c7SSrujana Challa {
3719d8e8c7SSrujana Challa int ret, irq;
38b33fa5ffSDan Carpenter int num_vec;
3919d8e8c7SSrujana Challa
4019d8e8c7SSrujana Challa num_vec = pci_msix_vec_count(cptvf->pdev);
4119d8e8c7SSrujana Challa if (num_vec <= 0)
4219d8e8c7SSrujana Challa return -EINVAL;
4319d8e8c7SSrujana Challa
4419d8e8c7SSrujana Challa /* Enable MSI-X */
4519d8e8c7SSrujana Challa ret = pci_alloc_irq_vectors(cptvf->pdev, num_vec, num_vec,
4619d8e8c7SSrujana Challa PCI_IRQ_MSIX);
4719d8e8c7SSrujana Challa if (ret < 0) {
4819d8e8c7SSrujana Challa dev_err(&cptvf->pdev->dev,
4919d8e8c7SSrujana Challa "Request for %d msix vectors failed\n", num_vec);
5019d8e8c7SSrujana Challa return ret;
5119d8e8c7SSrujana Challa }
5219d8e8c7SSrujana Challa irq = pci_irq_vector(cptvf->pdev, OTX2_CPT_VF_INT_VEC_E_MBOX);
5319d8e8c7SSrujana Challa /* Register VF<=>PF mailbox interrupt handler */
5419d8e8c7SSrujana Challa ret = devm_request_irq(&cptvf->pdev->dev, irq,
5519d8e8c7SSrujana Challa otx2_cptvf_pfvf_mbox_intr, 0,
5619d8e8c7SSrujana Challa "CPTPFVF Mbox", cptvf);
5719d8e8c7SSrujana Challa if (ret)
5819d8e8c7SSrujana Challa return ret;
5919d8e8c7SSrujana Challa /* Enable PF-VF mailbox interrupts */
6019d8e8c7SSrujana Challa cptvf_enable_pfvf_mbox_intrs(cptvf);
6119d8e8c7SSrujana Challa
6219d8e8c7SSrujana Challa ret = otx2_cpt_send_ready_msg(&cptvf->pfvf_mbox, cptvf->pdev);
6319d8e8c7SSrujana Challa if (ret) {
6419d8e8c7SSrujana Challa dev_warn(&cptvf->pdev->dev,
6519d8e8c7SSrujana Challa "PF not responding to mailbox, deferring probe\n");
6619d8e8c7SSrujana Challa cptvf_disable_pfvf_mbox_intrs(cptvf);
6719d8e8c7SSrujana Challa return -EPROBE_DEFER;
6819d8e8c7SSrujana Challa }
6919d8e8c7SSrujana Challa return 0;
7019d8e8c7SSrujana Challa }
7119d8e8c7SSrujana Challa
cptvf_pfvf_mbox_init(struct otx2_cptvf_dev * cptvf)7219d8e8c7SSrujana Challa static int cptvf_pfvf_mbox_init(struct otx2_cptvf_dev *cptvf)
7319d8e8c7SSrujana Challa {
744cd8c315SSrujana Challa struct pci_dev *pdev = cptvf->pdev;
754cd8c315SSrujana Challa resource_size_t offset, size;
7619d8e8c7SSrujana Challa int ret;
7719d8e8c7SSrujana Challa
788ae5c4d1STejun Heo cptvf->pfvf_mbox_wq =
798ae5c4d1STejun Heo alloc_ordered_workqueue("cpt_pfvf_mailbox",
808ae5c4d1STejun Heo WQ_HIGHPRI | WQ_MEM_RECLAIM);
8119d8e8c7SSrujana Challa if (!cptvf->pfvf_mbox_wq)
8219d8e8c7SSrujana Challa return -ENOMEM;
8319d8e8c7SSrujana Challa
844cd8c315SSrujana Challa if (test_bit(CN10K_MBOX, &cptvf->cap_flag)) {
854cd8c315SSrujana Challa /* For cn10k platform, VF mailbox region is in its BAR2
864cd8c315SSrujana Challa * register space
874cd8c315SSrujana Challa */
884cd8c315SSrujana Challa cptvf->pfvf_mbox_base = cptvf->reg_base +
894cd8c315SSrujana Challa CN10K_CPT_VF_MBOX_REGION;
904cd8c315SSrujana Challa } else {
914cd8c315SSrujana Challa offset = pci_resource_start(pdev, PCI_MBOX_BAR_NUM);
924cd8c315SSrujana Challa size = pci_resource_len(pdev, PCI_MBOX_BAR_NUM);
934cd8c315SSrujana Challa /* Map PF-VF mailbox memory */
944cd8c315SSrujana Challa cptvf->pfvf_mbox_base = devm_ioremap_wc(&pdev->dev, offset,
954cd8c315SSrujana Challa size);
964cd8c315SSrujana Challa if (!cptvf->pfvf_mbox_base) {
974cd8c315SSrujana Challa dev_err(&pdev->dev, "Unable to map BAR4\n");
984cd8c315SSrujana Challa ret = -ENOMEM;
994cd8c315SSrujana Challa goto free_wqe;
1004cd8c315SSrujana Challa }
1014cd8c315SSrujana Challa }
1024cd8c315SSrujana Challa
10319d8e8c7SSrujana Challa ret = otx2_mbox_init(&cptvf->pfvf_mbox, cptvf->pfvf_mbox_base,
1044cd8c315SSrujana Challa pdev, cptvf->reg_base, MBOX_DIR_VFPF, 1);
10519d8e8c7SSrujana Challa if (ret)
10619d8e8c7SSrujana Challa goto free_wqe;
10719d8e8c7SSrujana Challa
1084cd8c315SSrujana Challa ret = otx2_cpt_mbox_bbuf_init(cptvf, pdev);
1094cd8c315SSrujana Challa if (ret)
1104cd8c315SSrujana Challa goto destroy_mbox;
1114cd8c315SSrujana Challa
11219d8e8c7SSrujana Challa INIT_WORK(&cptvf->pfvf_mbox_work, otx2_cptvf_pfvf_mbox_handler);
11319d8e8c7SSrujana Challa return 0;
11419d8e8c7SSrujana Challa
1154cd8c315SSrujana Challa destroy_mbox:
1164cd8c315SSrujana Challa otx2_mbox_destroy(&cptvf->pfvf_mbox);
11719d8e8c7SSrujana Challa free_wqe:
11819d8e8c7SSrujana Challa destroy_workqueue(cptvf->pfvf_mbox_wq);
11919d8e8c7SSrujana Challa return ret;
12019d8e8c7SSrujana Challa }
12119d8e8c7SSrujana Challa
cptvf_pfvf_mbox_destroy(struct otx2_cptvf_dev * cptvf)12219d8e8c7SSrujana Challa static void cptvf_pfvf_mbox_destroy(struct otx2_cptvf_dev *cptvf)
12319d8e8c7SSrujana Challa {
12419d8e8c7SSrujana Challa destroy_workqueue(cptvf->pfvf_mbox_wq);
12519d8e8c7SSrujana Challa otx2_mbox_destroy(&cptvf->pfvf_mbox);
12619d8e8c7SSrujana Challa }
12719d8e8c7SSrujana Challa
cptlf_work_handler(unsigned long data)1288ec8015aSSrujana Challa static void cptlf_work_handler(unsigned long data)
1298ec8015aSSrujana Challa {
1308ec8015aSSrujana Challa otx2_cpt_post_process((struct otx2_cptlf_wqe *) data);
1318ec8015aSSrujana Challa }
1328ec8015aSSrujana Challa
cleanup_tasklet_work(struct otx2_cptlfs_info * lfs)1338ec8015aSSrujana Challa static void cleanup_tasklet_work(struct otx2_cptlfs_info *lfs)
1348ec8015aSSrujana Challa {
1358ec8015aSSrujana Challa int i;
1368ec8015aSSrujana Challa
1378ec8015aSSrujana Challa for (i = 0; i < lfs->lfs_num; i++) {
1388ec8015aSSrujana Challa if (!lfs->lf[i].wqe)
1398ec8015aSSrujana Challa continue;
1408ec8015aSSrujana Challa
1418ec8015aSSrujana Challa tasklet_kill(&lfs->lf[i].wqe->work);
1428ec8015aSSrujana Challa kfree(lfs->lf[i].wqe);
1438ec8015aSSrujana Challa lfs->lf[i].wqe = NULL;
1448ec8015aSSrujana Challa }
1458ec8015aSSrujana Challa }
1468ec8015aSSrujana Challa
init_tasklet_work(struct otx2_cptlfs_info * lfs)1478ec8015aSSrujana Challa static int init_tasklet_work(struct otx2_cptlfs_info *lfs)
1488ec8015aSSrujana Challa {
1498ec8015aSSrujana Challa struct otx2_cptlf_wqe *wqe;
1508ec8015aSSrujana Challa int i, ret = 0;
1518ec8015aSSrujana Challa
1528ec8015aSSrujana Challa for (i = 0; i < lfs->lfs_num; i++) {
1538ec8015aSSrujana Challa wqe = kzalloc(sizeof(struct otx2_cptlf_wqe), GFP_KERNEL);
1548ec8015aSSrujana Challa if (!wqe) {
1558ec8015aSSrujana Challa ret = -ENOMEM;
1568ec8015aSSrujana Challa goto cleanup_tasklet;
1578ec8015aSSrujana Challa }
1588ec8015aSSrujana Challa
1598ec8015aSSrujana Challa tasklet_init(&wqe->work, cptlf_work_handler, (u64) wqe);
1608ec8015aSSrujana Challa wqe->lfs = lfs;
1618ec8015aSSrujana Challa wqe->lf_num = i;
1628ec8015aSSrujana Challa lfs->lf[i].wqe = wqe;
1638ec8015aSSrujana Challa }
1648ec8015aSSrujana Challa return 0;
1658ec8015aSSrujana Challa
1668ec8015aSSrujana Challa cleanup_tasklet:
1678ec8015aSSrujana Challa cleanup_tasklet_work(lfs);
1688ec8015aSSrujana Challa return ret;
1698ec8015aSSrujana Challa }
1708ec8015aSSrujana Challa
free_pending_queues(struct otx2_cptlfs_info * lfs)1718ec8015aSSrujana Challa static void free_pending_queues(struct otx2_cptlfs_info *lfs)
1728ec8015aSSrujana Challa {
1738ec8015aSSrujana Challa int i;
1748ec8015aSSrujana Challa
1758ec8015aSSrujana Challa for (i = 0; i < lfs->lfs_num; i++) {
1768ec8015aSSrujana Challa kfree(lfs->lf[i].pqueue.head);
1778ec8015aSSrujana Challa lfs->lf[i].pqueue.head = NULL;
1788ec8015aSSrujana Challa }
1798ec8015aSSrujana Challa }
1808ec8015aSSrujana Challa
alloc_pending_queues(struct otx2_cptlfs_info * lfs)1818ec8015aSSrujana Challa static int alloc_pending_queues(struct otx2_cptlfs_info *lfs)
1828ec8015aSSrujana Challa {
1838ec8015aSSrujana Challa int size, ret, i;
1848ec8015aSSrujana Challa
1858ec8015aSSrujana Challa if (!lfs->lfs_num)
1868ec8015aSSrujana Challa return -EINVAL;
1878ec8015aSSrujana Challa
1888ec8015aSSrujana Challa for (i = 0; i < lfs->lfs_num; i++) {
1898ec8015aSSrujana Challa lfs->lf[i].pqueue.qlen = OTX2_CPT_INST_QLEN_MSGS;
1908ec8015aSSrujana Challa size = lfs->lf[i].pqueue.qlen *
1918ec8015aSSrujana Challa sizeof(struct otx2_cpt_pending_entry);
1928ec8015aSSrujana Challa
1938ec8015aSSrujana Challa lfs->lf[i].pqueue.head = kzalloc(size, GFP_KERNEL);
1948ec8015aSSrujana Challa if (!lfs->lf[i].pqueue.head) {
1958ec8015aSSrujana Challa ret = -ENOMEM;
1968ec8015aSSrujana Challa goto error;
1978ec8015aSSrujana Challa }
1988ec8015aSSrujana Challa
1998ec8015aSSrujana Challa /* Initialize spin lock */
2008ec8015aSSrujana Challa spin_lock_init(&lfs->lf[i].pqueue.lock);
2018ec8015aSSrujana Challa }
2028ec8015aSSrujana Challa return 0;
2038ec8015aSSrujana Challa
2048ec8015aSSrujana Challa error:
2058ec8015aSSrujana Challa free_pending_queues(lfs);
2068ec8015aSSrujana Challa return ret;
2078ec8015aSSrujana Challa }
2088ec8015aSSrujana Challa
lf_sw_cleanup(struct otx2_cptlfs_info * lfs)2098ec8015aSSrujana Challa static void lf_sw_cleanup(struct otx2_cptlfs_info *lfs)
2108ec8015aSSrujana Challa {
2118ec8015aSSrujana Challa cleanup_tasklet_work(lfs);
2128ec8015aSSrujana Challa free_pending_queues(lfs);
2138ec8015aSSrujana Challa }
2148ec8015aSSrujana Challa
lf_sw_init(struct otx2_cptlfs_info * lfs)2158ec8015aSSrujana Challa static int lf_sw_init(struct otx2_cptlfs_info *lfs)
2168ec8015aSSrujana Challa {
2178ec8015aSSrujana Challa int ret;
2188ec8015aSSrujana Challa
2198ec8015aSSrujana Challa ret = alloc_pending_queues(lfs);
2208ec8015aSSrujana Challa if (ret) {
2218ec8015aSSrujana Challa dev_err(&lfs->pdev->dev,
2228ec8015aSSrujana Challa "Allocating pending queues failed\n");
2238ec8015aSSrujana Challa return ret;
2248ec8015aSSrujana Challa }
2258ec8015aSSrujana Challa ret = init_tasklet_work(lfs);
2268ec8015aSSrujana Challa if (ret) {
2278ec8015aSSrujana Challa dev_err(&lfs->pdev->dev,
2288ec8015aSSrujana Challa "Tasklet work init failed\n");
2298ec8015aSSrujana Challa goto pending_queues_free;
2308ec8015aSSrujana Challa }
2318ec8015aSSrujana Challa return 0;
2328ec8015aSSrujana Challa
2338ec8015aSSrujana Challa pending_queues_free:
2348ec8015aSSrujana Challa free_pending_queues(lfs);
2358ec8015aSSrujana Challa return ret;
2368ec8015aSSrujana Challa }
2378ec8015aSSrujana Challa
cptvf_lf_shutdown(struct otx2_cptlfs_info * lfs)2388ec8015aSSrujana Challa static void cptvf_lf_shutdown(struct otx2_cptlfs_info *lfs)
2398ec8015aSSrujana Challa {
2408ec8015aSSrujana Challa atomic_set(&lfs->state, OTX2_CPTLF_IN_RESET);
2418ec8015aSSrujana Challa
2428ec8015aSSrujana Challa /* Remove interrupts affinity */
2438ec8015aSSrujana Challa otx2_cptlf_free_irqs_affinity(lfs);
2448ec8015aSSrujana Challa /* Disable instruction queue */
2458ec8015aSSrujana Challa otx2_cptlf_disable_iqueues(lfs);
2466f03f0e8SSrujana Challa /* Unregister crypto algorithms */
2476f03f0e8SSrujana Challa otx2_cpt_crypto_exit(lfs->pdev, THIS_MODULE);
2488ec8015aSSrujana Challa /* Unregister LFs interrupts */
2498ec8015aSSrujana Challa otx2_cptlf_unregister_interrupts(lfs);
2508ec8015aSSrujana Challa /* Cleanup LFs software side */
2518ec8015aSSrujana Challa lf_sw_cleanup(lfs);
252*8b18d5f5SBharat Bhushan /* Free instruction queues */
253*8b18d5f5SBharat Bhushan otx2_cpt_free_instruction_queues(lfs);
2548ec8015aSSrujana Challa /* Send request to detach LFs */
2558ec8015aSSrujana Challa otx2_cpt_detach_rsrcs_msg(lfs);
256*8b18d5f5SBharat Bhushan lfs->lfs_num = 0;
2578ec8015aSSrujana Challa }
2588ec8015aSSrujana Challa
cptvf_lf_init(struct otx2_cptvf_dev * cptvf)2598ec8015aSSrujana Challa static int cptvf_lf_init(struct otx2_cptvf_dev *cptvf)
2608ec8015aSSrujana Challa {
2618ec8015aSSrujana Challa struct otx2_cptlfs_info *lfs = &cptvf->lfs;
2628ec8015aSSrujana Challa struct device *dev = &cptvf->pdev->dev;
2638ec8015aSSrujana Challa int ret, lfs_num;
2648ec8015aSSrujana Challa u8 eng_grp_msk;
2658ec8015aSSrujana Challa
2668ec8015aSSrujana Challa /* Get engine group number for symmetric crypto */
2678ec8015aSSrujana Challa cptvf->lfs.kcrypto_eng_grp_num = OTX2_CPT_INVALID_CRYPTO_ENG_GRP;
2688ec8015aSSrujana Challa ret = otx2_cptvf_send_eng_grp_num_msg(cptvf, OTX2_CPT_SE_TYPES);
2698ec8015aSSrujana Challa if (ret)
2708ec8015aSSrujana Challa return ret;
2718ec8015aSSrujana Challa
2728ec8015aSSrujana Challa if (cptvf->lfs.kcrypto_eng_grp_num == OTX2_CPT_INVALID_CRYPTO_ENG_GRP) {
2738ec8015aSSrujana Challa dev_err(dev, "Engine group for kernel crypto not available\n");
2748ec8015aSSrujana Challa ret = -ENOENT;
2758ec8015aSSrujana Challa return ret;
2768ec8015aSSrujana Challa }
2778ec8015aSSrujana Challa eng_grp_msk = 1 << cptvf->lfs.kcrypto_eng_grp_num;
2788ec8015aSSrujana Challa
2798ec8015aSSrujana Challa ret = otx2_cptvf_send_kvf_limits_msg(cptvf);
2808ec8015aSSrujana Challa if (ret)
2818ec8015aSSrujana Challa return ret;
2828ec8015aSSrujana Challa
2838ec8015aSSrujana Challa lfs_num = cptvf->lfs.kvf_limits ? cptvf->lfs.kvf_limits :
2848ec8015aSSrujana Challa num_online_cpus();
285a4855a8cSSrujana Challa
286a4855a8cSSrujana Challa otx2_cptlf_set_dev_info(lfs, cptvf->pdev, cptvf->reg_base,
287a4855a8cSSrujana Challa &cptvf->pfvf_mbox, cptvf->blkaddr);
2888ec8015aSSrujana Challa ret = otx2_cptlf_init(lfs, eng_grp_msk, OTX2_CPT_QUEUE_HI_PRIO,
2898ec8015aSSrujana Challa lfs_num);
2908ec8015aSSrujana Challa if (ret)
2918ec8015aSSrujana Challa return ret;
2928ec8015aSSrujana Challa
2938ec8015aSSrujana Challa /* Get msix offsets for attached LFs */
2948ec8015aSSrujana Challa ret = otx2_cpt_msix_offset_msg(lfs);
2958ec8015aSSrujana Challa if (ret)
2968ec8015aSSrujana Challa goto cleanup_lf;
2978ec8015aSSrujana Challa
2988ec8015aSSrujana Challa /* Initialize LFs software side */
2998ec8015aSSrujana Challa ret = lf_sw_init(lfs);
3008ec8015aSSrujana Challa if (ret)
3018ec8015aSSrujana Challa goto cleanup_lf;
3028ec8015aSSrujana Challa
3038ec8015aSSrujana Challa /* Register LFs interrupts */
3048ec8015aSSrujana Challa ret = otx2_cptlf_register_interrupts(lfs);
3058ec8015aSSrujana Challa if (ret)
3068ec8015aSSrujana Challa goto cleanup_lf_sw;
3078ec8015aSSrujana Challa
3088ec8015aSSrujana Challa /* Set interrupts affinity */
3098ec8015aSSrujana Challa ret = otx2_cptlf_set_irqs_affinity(lfs);
3108ec8015aSSrujana Challa if (ret)
3118ec8015aSSrujana Challa goto unregister_intr;
3128ec8015aSSrujana Challa
3138ec8015aSSrujana Challa atomic_set(&lfs->state, OTX2_CPTLF_STARTED);
3146f03f0e8SSrujana Challa /* Register crypto algorithms */
3156f03f0e8SSrujana Challa ret = otx2_cpt_crypto_init(lfs->pdev, THIS_MODULE, lfs_num, 1);
3166f03f0e8SSrujana Challa if (ret) {
3176f03f0e8SSrujana Challa dev_err(&lfs->pdev->dev, "algorithms registration failed\n");
3186f03f0e8SSrujana Challa goto disable_irqs;
3196f03f0e8SSrujana Challa }
3208ec8015aSSrujana Challa return 0;
3218ec8015aSSrujana Challa
3226f03f0e8SSrujana Challa disable_irqs:
3236f03f0e8SSrujana Challa otx2_cptlf_free_irqs_affinity(lfs);
3248ec8015aSSrujana Challa unregister_intr:
3258ec8015aSSrujana Challa otx2_cptlf_unregister_interrupts(lfs);
3268ec8015aSSrujana Challa cleanup_lf_sw:
3278ec8015aSSrujana Challa lf_sw_cleanup(lfs);
3288ec8015aSSrujana Challa cleanup_lf:
3298ec8015aSSrujana Challa otx2_cptlf_shutdown(lfs);
3308ec8015aSSrujana Challa
3318ec8015aSSrujana Challa return ret;
3328ec8015aSSrujana Challa }
3338ec8015aSSrujana Challa
otx2_cptvf_probe(struct pci_dev * pdev,const struct pci_device_id * ent)33419d8e8c7SSrujana Challa static int otx2_cptvf_probe(struct pci_dev *pdev,
33519d8e8c7SSrujana Challa const struct pci_device_id *ent)
33619d8e8c7SSrujana Challa {
33719d8e8c7SSrujana Challa struct device *dev = &pdev->dev;
33819d8e8c7SSrujana Challa struct otx2_cptvf_dev *cptvf;
33919d8e8c7SSrujana Challa int ret;
34019d8e8c7SSrujana Challa
34119d8e8c7SSrujana Challa cptvf = devm_kzalloc(dev, sizeof(*cptvf), GFP_KERNEL);
34219d8e8c7SSrujana Challa if (!cptvf)
34319d8e8c7SSrujana Challa return -ENOMEM;
34419d8e8c7SSrujana Challa
34519d8e8c7SSrujana Challa ret = pcim_enable_device(pdev);
34619d8e8c7SSrujana Challa if (ret) {
34719d8e8c7SSrujana Challa dev_err(dev, "Failed to enable PCI device\n");
34819d8e8c7SSrujana Challa goto clear_drvdata;
34919d8e8c7SSrujana Challa }
35019d8e8c7SSrujana Challa
35119d8e8c7SSrujana Challa ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
35219d8e8c7SSrujana Challa if (ret) {
35319d8e8c7SSrujana Challa dev_err(dev, "Unable to get usable DMA configuration\n");
35419d8e8c7SSrujana Challa goto clear_drvdata;
35519d8e8c7SSrujana Challa }
35619d8e8c7SSrujana Challa /* Map VF's configuration registers */
35719d8e8c7SSrujana Challa ret = pcim_iomap_regions_request_all(pdev, 1 << PCI_PF_REG_BAR_NUM,
35819d8e8c7SSrujana Challa OTX2_CPTVF_DRV_NAME);
35919d8e8c7SSrujana Challa if (ret) {
36019d8e8c7SSrujana Challa dev_err(dev, "Couldn't get PCI resources 0x%x\n", ret);
36119d8e8c7SSrujana Challa goto clear_drvdata;
36219d8e8c7SSrujana Challa }
36319d8e8c7SSrujana Challa pci_set_master(pdev);
36419d8e8c7SSrujana Challa pci_set_drvdata(pdev, cptvf);
36519d8e8c7SSrujana Challa cptvf->pdev = pdev;
36619d8e8c7SSrujana Challa
36719d8e8c7SSrujana Challa cptvf->reg_base = pcim_iomap_table(pdev)[PCI_PF_REG_BAR_NUM];
36819d8e8c7SSrujana Challa
3694cd8c315SSrujana Challa otx2_cpt_set_hw_caps(pdev, &cptvf->cap_flag);
370eb33cd91SSrujana Challa
371eb33cd91SSrujana Challa ret = cn10k_cptvf_lmtst_init(cptvf);
372eb33cd91SSrujana Challa if (ret)
373eb33cd91SSrujana Challa goto clear_drvdata;
374eb33cd91SSrujana Challa
37519d8e8c7SSrujana Challa /* Initialize PF<=>VF mailbox */
37619d8e8c7SSrujana Challa ret = cptvf_pfvf_mbox_init(cptvf);
37719d8e8c7SSrujana Challa if (ret)
37819d8e8c7SSrujana Challa goto clear_drvdata;
37919d8e8c7SSrujana Challa
38019d8e8c7SSrujana Challa /* Register interrupts */
38119d8e8c7SSrujana Challa ret = cptvf_register_interrupts(cptvf);
38219d8e8c7SSrujana Challa if (ret)
38319d8e8c7SSrujana Challa goto destroy_pfvf_mbox;
38419d8e8c7SSrujana Challa
385a4855a8cSSrujana Challa cptvf->blkaddr = BLKADDR_CPT0;
3868ec8015aSSrujana Challa /* Initialize CPT LFs */
3878ec8015aSSrujana Challa ret = cptvf_lf_init(cptvf);
3888ec8015aSSrujana Challa if (ret)
3898ec8015aSSrujana Challa goto unregister_interrupts;
3908ec8015aSSrujana Challa
39119d8e8c7SSrujana Challa return 0;
39219d8e8c7SSrujana Challa
3938ec8015aSSrujana Challa unregister_interrupts:
3948ec8015aSSrujana Challa cptvf_disable_pfvf_mbox_intrs(cptvf);
39519d8e8c7SSrujana Challa destroy_pfvf_mbox:
39619d8e8c7SSrujana Challa cptvf_pfvf_mbox_destroy(cptvf);
39719d8e8c7SSrujana Challa clear_drvdata:
39819d8e8c7SSrujana Challa pci_set_drvdata(pdev, NULL);
39919d8e8c7SSrujana Challa
40019d8e8c7SSrujana Challa return ret;
40119d8e8c7SSrujana Challa }
40219d8e8c7SSrujana Challa
otx2_cptvf_remove(struct pci_dev * pdev)40319d8e8c7SSrujana Challa static void otx2_cptvf_remove(struct pci_dev *pdev)
40419d8e8c7SSrujana Challa {
40519d8e8c7SSrujana Challa struct otx2_cptvf_dev *cptvf = pci_get_drvdata(pdev);
40619d8e8c7SSrujana Challa
40719d8e8c7SSrujana Challa if (!cptvf) {
40819d8e8c7SSrujana Challa dev_err(&pdev->dev, "Invalid CPT VF device.\n");
40919d8e8c7SSrujana Challa return;
41019d8e8c7SSrujana Challa }
4118ec8015aSSrujana Challa cptvf_lf_shutdown(&cptvf->lfs);
41219d8e8c7SSrujana Challa /* Disable PF-VF mailbox interrupt */
41319d8e8c7SSrujana Challa cptvf_disable_pfvf_mbox_intrs(cptvf);
41419d8e8c7SSrujana Challa /* Destroy PF-VF mbox */
41519d8e8c7SSrujana Challa cptvf_pfvf_mbox_destroy(cptvf);
41619d8e8c7SSrujana Challa pci_set_drvdata(pdev, NULL);
41719d8e8c7SSrujana Challa }
41819d8e8c7SSrujana Challa
41919d8e8c7SSrujana Challa /* Supported devices */
42019d8e8c7SSrujana Challa static const struct pci_device_id otx2_cptvf_id_table[] = {
42119d8e8c7SSrujana Challa {PCI_VDEVICE(CAVIUM, OTX2_CPT_PCI_VF_DEVICE_ID), 0},
4224cd8c315SSrujana Challa {PCI_VDEVICE(CAVIUM, CN10K_CPT_PCI_VF_DEVICE_ID), 0},
42319d8e8c7SSrujana Challa { 0, } /* end of table */
42419d8e8c7SSrujana Challa };
42519d8e8c7SSrujana Challa
42619d8e8c7SSrujana Challa static struct pci_driver otx2_cptvf_pci_driver = {
42719d8e8c7SSrujana Challa .name = OTX2_CPTVF_DRV_NAME,
42819d8e8c7SSrujana Challa .id_table = otx2_cptvf_id_table,
42919d8e8c7SSrujana Challa .probe = otx2_cptvf_probe,
43019d8e8c7SSrujana Challa .remove = otx2_cptvf_remove,
43119d8e8c7SSrujana Challa };
43219d8e8c7SSrujana Challa
43319d8e8c7SSrujana Challa module_pci_driver(otx2_cptvf_pci_driver);
43419d8e8c7SSrujana Challa
43572bc4e71SAlexander Lobakin MODULE_IMPORT_NS(CRYPTO_DEV_OCTEONTX2_CPT);
43672bc4e71SAlexander Lobakin
43719d8e8c7SSrujana Challa MODULE_AUTHOR("Marvell");
4384cd8c315SSrujana Challa MODULE_DESCRIPTION("Marvell RVU CPT Virtual Function Driver");
43919d8e8c7SSrujana Challa MODULE_LICENSE("GPL v2");
44019d8e8c7SSrujana Challa MODULE_DEVICE_TABLE(pci, otx2_cptvf_id_table);
441