Path: blob/master/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
26285 views
// SPDX-License-Identifier: GPL-2.0-only1/* Copyright (C) 2020 Marvell. */23#include "otx2_cpt_common.h"4#include "otx2_cptvf.h"5#include "otx2_cptlf.h"6#include "otx2_cptvf_algs.h"7#include "cn10k_cpt.h"8#include <rvu_reg.h>910#define OTX2_CPTVF_DRV_NAME "rvu_cptvf"1112static void cptvf_enable_pfvf_mbox_intrs(struct otx2_cptvf_dev *cptvf)13{14/* Clear interrupt if any */15otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0, OTX2_RVU_VF_INT,160x1ULL);1718/* Enable PF-VF interrupt */19otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0,20OTX2_RVU_VF_INT_ENA_W1S, 0x1ULL);21}2223static void cptvf_disable_pfvf_mbox_intrs(struct otx2_cptvf_dev *cptvf)24{25/* Disable PF-VF interrupt */26otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0,27OTX2_RVU_VF_INT_ENA_W1C, 0x1ULL);2829/* Clear interrupt if any */30otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0, OTX2_RVU_VF_INT,310x1ULL);32}3334static int cptvf_register_interrupts(struct otx2_cptvf_dev *cptvf)35{36int ret, irq;37int num_vec;3839num_vec = pci_msix_vec_count(cptvf->pdev);40if (num_vec <= 0)41return -EINVAL;4243/* Enable MSI-X */44ret = pci_alloc_irq_vectors(cptvf->pdev, num_vec, num_vec,45PCI_IRQ_MSIX);46if (ret < 0) {47dev_err(&cptvf->pdev->dev,48"Request for %d msix vectors failed\n", num_vec);49return ret;50}51irq = pci_irq_vector(cptvf->pdev, OTX2_CPT_VF_INT_VEC_E_MBOX);52/* Register VF<=>PF mailbox interrupt handler */53ret = devm_request_irq(&cptvf->pdev->dev, irq,54otx2_cptvf_pfvf_mbox_intr, 0,55"CPTPFVF Mbox", cptvf);56if (ret)57return ret;58/* Enable PF-VF mailbox interrupts */59cptvf_enable_pfvf_mbox_intrs(cptvf);6061ret = otx2_cpt_send_ready_msg(&cptvf->pfvf_mbox, cptvf->pdev);62if (ret) {63dev_warn(&cptvf->pdev->dev,64"PF not responding to mailbox, deferring probe\n");65cptvf_disable_pfvf_mbox_intrs(cptvf);66return -EPROBE_DEFER;67}68return 0;69}7071static int cptvf_pfvf_mbox_init(struct otx2_cptvf_dev *cptvf)72{73struct pci_dev *pdev = cptvf->pdev;74resource_size_t offset, size;75int ret;7677cptvf->pfvf_mbox_wq =78alloc_ordered_workqueue("cpt_pfvf_mailbox",79WQ_HIGHPRI | WQ_MEM_RECLAIM);80if (!cptvf->pfvf_mbox_wq)81return -ENOMEM;8283if (test_bit(CN10K_MBOX, &cptvf->cap_flag)) {84/* For cn10k platform, VF mailbox region is in its BAR285* register space86*/87cptvf->pfvf_mbox_base = cptvf->reg_base +88CN10K_CPT_VF_MBOX_REGION;89} else {90offset = pci_resource_start(pdev, PCI_MBOX_BAR_NUM);91size = pci_resource_len(pdev, PCI_MBOX_BAR_NUM);92/* Map PF-VF mailbox memory */93cptvf->pfvf_mbox_base = devm_ioremap_wc(&pdev->dev, offset,94size);95if (!cptvf->pfvf_mbox_base) {96dev_err(&pdev->dev, "Unable to map BAR4\n");97ret = -ENOMEM;98goto free_wqe;99}100}101102ret = otx2_mbox_init(&cptvf->pfvf_mbox, cptvf->pfvf_mbox_base,103pdev, cptvf->reg_base, MBOX_DIR_VFPF, 1);104if (ret)105goto free_wqe;106107ret = otx2_cpt_mbox_bbuf_init(cptvf, pdev);108if (ret)109goto destroy_mbox;110111INIT_WORK(&cptvf->pfvf_mbox_work, otx2_cptvf_pfvf_mbox_handler);112return 0;113114destroy_mbox:115otx2_mbox_destroy(&cptvf->pfvf_mbox);116free_wqe:117destroy_workqueue(cptvf->pfvf_mbox_wq);118return ret;119}120121static void cptvf_pfvf_mbox_destroy(struct otx2_cptvf_dev *cptvf)122{123destroy_workqueue(cptvf->pfvf_mbox_wq);124otx2_mbox_destroy(&cptvf->pfvf_mbox);125}126127static void cptlf_work_handler(unsigned long data)128{129otx2_cpt_post_process((struct otx2_cptlf_wqe *) data);130}131132static void cleanup_tasklet_work(struct otx2_cptlfs_info *lfs)133{134int i;135136for (i = 0; i < lfs->lfs_num; i++) {137if (!lfs->lf[i].wqe)138continue;139140tasklet_kill(&lfs->lf[i].wqe->work);141kfree(lfs->lf[i].wqe);142lfs->lf[i].wqe = NULL;143}144}145146static int init_tasklet_work(struct otx2_cptlfs_info *lfs)147{148struct otx2_cptlf_wqe *wqe;149int i, ret = 0;150151for (i = 0; i < lfs->lfs_num; i++) {152wqe = kzalloc(sizeof(struct otx2_cptlf_wqe), GFP_KERNEL);153if (!wqe) {154ret = -ENOMEM;155goto cleanup_tasklet;156}157158tasklet_init(&wqe->work, cptlf_work_handler, (u64) wqe);159wqe->lfs = lfs;160wqe->lf_num = i;161lfs->lf[i].wqe = wqe;162}163return 0;164165cleanup_tasklet:166cleanup_tasklet_work(lfs);167return ret;168}169170static void free_pending_queues(struct otx2_cptlfs_info *lfs)171{172int i;173174for (i = 0; i < lfs->lfs_num; i++) {175kfree(lfs->lf[i].pqueue.head);176lfs->lf[i].pqueue.head = NULL;177}178}179180static int alloc_pending_queues(struct otx2_cptlfs_info *lfs)181{182int size, ret, i;183184if (!lfs->lfs_num)185return -EINVAL;186187for (i = 0; i < lfs->lfs_num; i++) {188lfs->lf[i].pqueue.qlen = OTX2_CPT_INST_QLEN_MSGS;189size = lfs->lf[i].pqueue.qlen *190sizeof(struct otx2_cpt_pending_entry);191192lfs->lf[i].pqueue.head = kzalloc(size, GFP_KERNEL);193if (!lfs->lf[i].pqueue.head) {194ret = -ENOMEM;195goto error;196}197198/* Initialize spin lock */199spin_lock_init(&lfs->lf[i].pqueue.lock);200}201return 0;202203error:204free_pending_queues(lfs);205return ret;206}207208static void lf_sw_cleanup(struct otx2_cptlfs_info *lfs)209{210cleanup_tasklet_work(lfs);211free_pending_queues(lfs);212}213214static int lf_sw_init(struct otx2_cptlfs_info *lfs)215{216int ret;217218ret = alloc_pending_queues(lfs);219if (ret) {220dev_err(&lfs->pdev->dev,221"Allocating pending queues failed\n");222return ret;223}224ret = init_tasklet_work(lfs);225if (ret) {226dev_err(&lfs->pdev->dev,227"Tasklet work init failed\n");228goto pending_queues_free;229}230return 0;231232pending_queues_free:233free_pending_queues(lfs);234return ret;235}236237static void cptvf_lf_shutdown(struct otx2_cptlfs_info *lfs)238{239atomic_set(&lfs->state, OTX2_CPTLF_IN_RESET);240241/* Remove interrupts affinity */242otx2_cptlf_free_irqs_affinity(lfs);243/* Disable instruction queue */244otx2_cptlf_disable_iqueues(lfs);245/* Unregister crypto algorithms */246otx2_cpt_crypto_exit(lfs->pdev, THIS_MODULE);247/* Unregister LFs interrupts */248otx2_cptlf_unregister_misc_interrupts(lfs);249otx2_cptlf_unregister_done_interrupts(lfs);250/* Cleanup LFs software side */251lf_sw_cleanup(lfs);252/* Free instruction queues */253otx2_cpt_free_instruction_queues(lfs);254/* Send request to detach LFs */255otx2_cpt_detach_rsrcs_msg(lfs);256lfs->lfs_num = 0;257}258259static int cptvf_lf_init(struct otx2_cptvf_dev *cptvf)260{261struct otx2_cptlfs_info *lfs = &cptvf->lfs;262struct device *dev = &cptvf->pdev->dev;263int ret, lfs_num;264u8 eng_grp_msk;265266/* Get engine group number for symmetric crypto */267cptvf->lfs.kcrypto_se_eng_grp_num = OTX2_CPT_INVALID_CRYPTO_ENG_GRP;268ret = otx2_cptvf_send_eng_grp_num_msg(cptvf, OTX2_CPT_SE_TYPES);269if (ret)270return ret;271272if (cptvf->lfs.kcrypto_se_eng_grp_num ==273OTX2_CPT_INVALID_CRYPTO_ENG_GRP) {274dev_err(dev,275"Symmetric Engine group for crypto not available\n");276return -ENOENT;277}278279/* Get engine group number for asymmetric crypto */280cptvf->lfs.kcrypto_ae_eng_grp_num = OTX2_CPT_INVALID_CRYPTO_ENG_GRP;281ret = otx2_cptvf_send_eng_grp_num_msg(cptvf, OTX2_CPT_AE_TYPES);282if (ret)283return ret;284285if (cptvf->lfs.kcrypto_ae_eng_grp_num ==286OTX2_CPT_INVALID_CRYPTO_ENG_GRP) {287dev_err(dev,288"Asymmetric Engine group for crypto not available\n");289return -ENOENT;290}291292eng_grp_msk = BIT(cptvf->lfs.kcrypto_se_eng_grp_num) |293BIT(cptvf->lfs.kcrypto_ae_eng_grp_num);294295ret = otx2_cptvf_send_kvf_limits_msg(cptvf);296if (ret)297return ret;298299lfs_num = cptvf->lfs.kvf_limits;300301ret = otx2_cptlf_init(lfs, eng_grp_msk, OTX2_CPT_QUEUE_HI_PRIO,302lfs_num);303if (ret)304return ret;305306/* Get msix offsets for attached LFs */307ret = otx2_cpt_msix_offset_msg(lfs);308if (ret)309goto cleanup_lf;310311/* Initialize LFs software side */312ret = lf_sw_init(lfs);313if (ret)314goto cleanup_lf;315316/* Register LFs interrupts */317ret = otx2_cptlf_register_misc_interrupts(lfs);318if (ret)319goto cleanup_lf_sw;320321ret = otx2_cptlf_register_done_interrupts(lfs);322if (ret)323goto cleanup_lf_sw;324325/* Set interrupts affinity */326ret = otx2_cptlf_set_irqs_affinity(lfs);327if (ret)328goto unregister_intr;329330atomic_set(&lfs->state, OTX2_CPTLF_STARTED);331/* Register crypto algorithms */332ret = otx2_cpt_crypto_init(lfs->pdev, THIS_MODULE, lfs_num, 1);333if (ret) {334dev_err(&lfs->pdev->dev, "algorithms registration failed\n");335goto disable_irqs;336}337return 0;338339disable_irqs:340otx2_cptlf_free_irqs_affinity(lfs);341unregister_intr:342otx2_cptlf_unregister_misc_interrupts(lfs);343otx2_cptlf_unregister_done_interrupts(lfs);344cleanup_lf_sw:345lf_sw_cleanup(lfs);346cleanup_lf:347otx2_cptlf_shutdown(lfs);348349return ret;350}351352static int otx2_cptvf_probe(struct pci_dev *pdev,353const struct pci_device_id *ent)354{355struct device *dev = &pdev->dev;356struct otx2_cptvf_dev *cptvf;357int ret;358359cptvf = devm_kzalloc(dev, sizeof(*cptvf), GFP_KERNEL);360if (!cptvf)361return -ENOMEM;362363ret = pcim_enable_device(pdev);364if (ret) {365dev_err(dev, "Failed to enable PCI device\n");366goto clear_drvdata;367}368369ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));370if (ret) {371dev_err(dev, "Unable to get usable DMA configuration\n");372goto clear_drvdata;373}374375ret = pcim_request_all_regions(pdev, OTX2_CPTVF_DRV_NAME);376if (ret) {377dev_err(dev, "Couldn't get PCI resources 0x%x\n", ret);378goto clear_drvdata;379}380pci_set_master(pdev);381pci_set_drvdata(pdev, cptvf);382cptvf->pdev = pdev;383384/* Map VF's configuration registers */385cptvf->reg_base = pcim_iomap(pdev, PCI_PF_REG_BAR_NUM, 0);386if (!cptvf->reg_base) {387ret = -ENOMEM;388dev_err(dev, "Couldn't ioremap PCI resource 0x%x\n", ret);389goto clear_drvdata;390}391392otx2_cpt_set_hw_caps(pdev, &cptvf->cap_flag);393394/* Initialize PF<=>VF mailbox */395ret = cptvf_pfvf_mbox_init(cptvf);396if (ret)397goto clear_drvdata;398399/* Register interrupts */400ret = cptvf_register_interrupts(cptvf);401if (ret)402goto destroy_pfvf_mbox;403404cptvf->blkaddr = BLKADDR_CPT0;405406cptvf_hw_ops_get(cptvf);407408otx2_cptlf_set_dev_info(&cptvf->lfs, cptvf->pdev, cptvf->reg_base,409&cptvf->pfvf_mbox, cptvf->blkaddr);410411ret = otx2_cptvf_send_caps_msg(cptvf);412if (ret) {413dev_err(&pdev->dev, "Couldn't get CPT engine capabilities.\n");414goto unregister_interrupts;415}416if (cptvf->eng_caps[OTX2_CPT_SE_TYPES] & BIT_ULL(35))417cptvf->lfs.ops->cpt_sg_info_create = cn10k_sgv2_info_create;418419ret = cn10k_cptvf_lmtst_init(cptvf);420if (ret)421goto unregister_interrupts;422423/* Initialize CPT LFs */424ret = cptvf_lf_init(cptvf);425if (ret)426goto free_lmtst;427428return 0;429430free_lmtst:431cn10k_cpt_lmtst_free(pdev, &cptvf->lfs);432unregister_interrupts:433cptvf_disable_pfvf_mbox_intrs(cptvf);434destroy_pfvf_mbox:435cptvf_pfvf_mbox_destroy(cptvf);436clear_drvdata:437pci_set_drvdata(pdev, NULL);438439return ret;440}441442static void otx2_cptvf_remove(struct pci_dev *pdev)443{444struct otx2_cptvf_dev *cptvf = pci_get_drvdata(pdev);445446if (!cptvf) {447dev_err(&pdev->dev, "Invalid CPT VF device.\n");448return;449}450cptvf_lf_shutdown(&cptvf->lfs);451/* Disable PF-VF mailbox interrupt */452cptvf_disable_pfvf_mbox_intrs(cptvf);453/* Destroy PF-VF mbox */454cptvf_pfvf_mbox_destroy(cptvf);455/* Free LMTST memory */456cn10k_cpt_lmtst_free(pdev, &cptvf->lfs);457pci_set_drvdata(pdev, NULL);458}459460/* Supported devices */461static const struct pci_device_id otx2_cptvf_id_table[] = {462{PCI_VDEVICE(CAVIUM, OTX2_CPT_PCI_VF_DEVICE_ID), 0},463{PCI_VDEVICE(CAVIUM, CN10K_CPT_PCI_VF_DEVICE_ID), 0},464{ 0, } /* end of table */465};466467static struct pci_driver otx2_cptvf_pci_driver = {468.name = OTX2_CPTVF_DRV_NAME,469.id_table = otx2_cptvf_id_table,470.probe = otx2_cptvf_probe,471.remove = otx2_cptvf_remove,472};473474module_pci_driver(otx2_cptvf_pci_driver);475476MODULE_IMPORT_NS("CRYPTO_DEV_OCTEONTX2_CPT");477478MODULE_AUTHOR("Marvell");479MODULE_DESCRIPTION("Marvell RVU CPT Virtual Function Driver");480MODULE_LICENSE("GPL v2");481MODULE_DEVICE_TABLE(pci, otx2_cptvf_id_table);482483484