18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Marvell OcteonTX CPT driver 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2019 Marvell International Ltd. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 78c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as 88c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include "otx_cptvf.h" 148c2ecf20Sopenharmony_ci#include "otx_cptvf_algs.h" 158c2ecf20Sopenharmony_ci#include "otx_cptvf_reqmgr.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#define DRV_NAME "octeontx-cptvf" 188c2ecf20Sopenharmony_ci#define DRV_VERSION "1.0" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic void vq_work_handler(unsigned long data) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci struct otx_cptvf_wqe_info *cwqe_info = 238c2ecf20Sopenharmony_ci (struct otx_cptvf_wqe_info *) data; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci otx_cpt_post_process(&cwqe_info->vq_wqe[0]); 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic int init_worker_threads(struct otx_cptvf *cptvf) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 318c2ecf20Sopenharmony_ci struct otx_cptvf_wqe_info *cwqe_info; 328c2ecf20Sopenharmony_ci int i; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci cwqe_info = kzalloc(sizeof(*cwqe_info), GFP_KERNEL); 358c2ecf20Sopenharmony_ci if (!cwqe_info) 368c2ecf20Sopenharmony_ci return -ENOMEM; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci if (cptvf->num_queues) { 398c2ecf20Sopenharmony_ci dev_dbg(&pdev->dev, "Creating VQ worker threads (%d)\n", 408c2ecf20Sopenharmony_ci cptvf->num_queues); 418c2ecf20Sopenharmony_ci } 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci for (i = 0; i < cptvf->num_queues; i++) { 448c2ecf20Sopenharmony_ci tasklet_init(&cwqe_info->vq_wqe[i].twork, vq_work_handler, 458c2ecf20Sopenharmony_ci (u64)cwqe_info); 468c2ecf20Sopenharmony_ci cwqe_info->vq_wqe[i].cptvf = cptvf; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci cptvf->wqe_info = cwqe_info; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci return 0; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic void cleanup_worker_threads(struct otx_cptvf *cptvf) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 568c2ecf20Sopenharmony_ci struct otx_cptvf_wqe_info *cwqe_info; 578c2ecf20Sopenharmony_ci int i; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci cwqe_info = (struct otx_cptvf_wqe_info *)cptvf->wqe_info; 608c2ecf20Sopenharmony_ci if (!cwqe_info) 618c2ecf20Sopenharmony_ci return; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (cptvf->num_queues) { 648c2ecf20Sopenharmony_ci dev_dbg(&pdev->dev, "Cleaning VQ worker threads (%u)\n", 658c2ecf20Sopenharmony_ci cptvf->num_queues); 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci for (i = 0; i < cptvf->num_queues; i++) 698c2ecf20Sopenharmony_ci tasklet_kill(&cwqe_info->vq_wqe[i].twork); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci kfree_sensitive(cwqe_info); 728c2ecf20Sopenharmony_ci cptvf->wqe_info = NULL; 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic void free_pending_queues(struct otx_cpt_pending_qinfo *pqinfo) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct otx_cpt_pending_queue *queue; 788c2ecf20Sopenharmony_ci int i; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci for_each_pending_queue(pqinfo, queue, i) { 818c2ecf20Sopenharmony_ci if (!queue->head) 828c2ecf20Sopenharmony_ci continue; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci /* free single queue */ 858c2ecf20Sopenharmony_ci kfree_sensitive((queue->head)); 868c2ecf20Sopenharmony_ci queue->front = 0; 878c2ecf20Sopenharmony_ci queue->rear = 0; 888c2ecf20Sopenharmony_ci queue->qlen = 0; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci pqinfo->num_queues = 0; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic int alloc_pending_queues(struct otx_cpt_pending_qinfo *pqinfo, u32 qlen, 948c2ecf20Sopenharmony_ci u32 num_queues) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci struct otx_cpt_pending_queue *queue = NULL; 978c2ecf20Sopenharmony_ci size_t size; 988c2ecf20Sopenharmony_ci int ret; 998c2ecf20Sopenharmony_ci u32 i; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci pqinfo->num_queues = num_queues; 1028c2ecf20Sopenharmony_ci size = (qlen * sizeof(struct otx_cpt_pending_entry)); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci for_each_pending_queue(pqinfo, queue, i) { 1058c2ecf20Sopenharmony_ci queue->head = kzalloc((size), GFP_KERNEL); 1068c2ecf20Sopenharmony_ci if (!queue->head) { 1078c2ecf20Sopenharmony_ci ret = -ENOMEM; 1088c2ecf20Sopenharmony_ci goto pending_qfail; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci queue->pending_count = 0; 1128c2ecf20Sopenharmony_ci queue->front = 0; 1138c2ecf20Sopenharmony_ci queue->rear = 0; 1148c2ecf20Sopenharmony_ci queue->qlen = qlen; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* init queue spin lock */ 1178c2ecf20Sopenharmony_ci spin_lock_init(&queue->lock); 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci return 0; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cipending_qfail: 1228c2ecf20Sopenharmony_ci free_pending_queues(pqinfo); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return ret; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic int init_pending_queues(struct otx_cptvf *cptvf, u32 qlen, 1288c2ecf20Sopenharmony_ci u32 num_queues) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 1318c2ecf20Sopenharmony_ci int ret; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci if (!num_queues) 1348c2ecf20Sopenharmony_ci return 0; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci ret = alloc_pending_queues(&cptvf->pqinfo, qlen, num_queues); 1378c2ecf20Sopenharmony_ci if (ret) { 1388c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to setup pending queues (%u)\n", 1398c2ecf20Sopenharmony_ci num_queues); 1408c2ecf20Sopenharmony_ci return ret; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci return 0; 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic void cleanup_pending_queues(struct otx_cptvf *cptvf) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (!cptvf->num_queues) 1508c2ecf20Sopenharmony_ci return; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci dev_dbg(&pdev->dev, "Cleaning VQ pending queue (%u)\n", 1538c2ecf20Sopenharmony_ci cptvf->num_queues); 1548c2ecf20Sopenharmony_ci free_pending_queues(&cptvf->pqinfo); 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic void free_command_queues(struct otx_cptvf *cptvf, 1588c2ecf20Sopenharmony_ci struct otx_cpt_cmd_qinfo *cqinfo) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci struct otx_cpt_cmd_queue *queue = NULL; 1618c2ecf20Sopenharmony_ci struct otx_cpt_cmd_chunk *chunk = NULL; 1628c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 1638c2ecf20Sopenharmony_ci int i; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* clean up for each queue */ 1668c2ecf20Sopenharmony_ci for (i = 0; i < cptvf->num_queues; i++) { 1678c2ecf20Sopenharmony_ci queue = &cqinfo->queue[i]; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci while (!list_empty(&cqinfo->queue[i].chead)) { 1708c2ecf20Sopenharmony_ci chunk = list_first_entry(&cqinfo->queue[i].chead, 1718c2ecf20Sopenharmony_ci struct otx_cpt_cmd_chunk, nextchunk); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci dma_free_coherent(&pdev->dev, chunk->size, 1748c2ecf20Sopenharmony_ci chunk->head, 1758c2ecf20Sopenharmony_ci chunk->dma_addr); 1768c2ecf20Sopenharmony_ci chunk->head = NULL; 1778c2ecf20Sopenharmony_ci chunk->dma_addr = 0; 1788c2ecf20Sopenharmony_ci list_del(&chunk->nextchunk); 1798c2ecf20Sopenharmony_ci kfree_sensitive(chunk); 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci queue->num_chunks = 0; 1828c2ecf20Sopenharmony_ci queue->idx = 0; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic int alloc_command_queues(struct otx_cptvf *cptvf, 1888c2ecf20Sopenharmony_ci struct otx_cpt_cmd_qinfo *cqinfo, 1898c2ecf20Sopenharmony_ci u32 qlen) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci struct otx_cpt_cmd_chunk *curr, *first, *last; 1928c2ecf20Sopenharmony_ci struct otx_cpt_cmd_queue *queue = NULL; 1938c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 1948c2ecf20Sopenharmony_ci size_t q_size, c_size, rem_q_size; 1958c2ecf20Sopenharmony_ci u32 qcsize_bytes; 1968c2ecf20Sopenharmony_ci int i; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci /* Qsize in dwords, needed for SADDR config, 1-next chunk pointer */ 2008c2ecf20Sopenharmony_ci cptvf->qsize = min(qlen, cqinfo->qchunksize) * 2018c2ecf20Sopenharmony_ci OTX_CPT_NEXT_CHUNK_PTR_SIZE + 1; 2028c2ecf20Sopenharmony_ci /* Qsize in bytes to create space for alignment */ 2038c2ecf20Sopenharmony_ci q_size = qlen * OTX_CPT_INST_SIZE; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci qcsize_bytes = cqinfo->qchunksize * OTX_CPT_INST_SIZE; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* per queue initialization */ 2088c2ecf20Sopenharmony_ci for (i = 0; i < cptvf->num_queues; i++) { 2098c2ecf20Sopenharmony_ci c_size = 0; 2108c2ecf20Sopenharmony_ci rem_q_size = q_size; 2118c2ecf20Sopenharmony_ci first = NULL; 2128c2ecf20Sopenharmony_ci last = NULL; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci queue = &cqinfo->queue[i]; 2158c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&queue->chead); 2168c2ecf20Sopenharmony_ci do { 2178c2ecf20Sopenharmony_ci curr = kzalloc(sizeof(*curr), GFP_KERNEL); 2188c2ecf20Sopenharmony_ci if (!curr) 2198c2ecf20Sopenharmony_ci goto cmd_qfail; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci c_size = (rem_q_size > qcsize_bytes) ? qcsize_bytes : 2228c2ecf20Sopenharmony_ci rem_q_size; 2238c2ecf20Sopenharmony_ci curr->head = dma_alloc_coherent(&pdev->dev, 2248c2ecf20Sopenharmony_ci c_size + OTX_CPT_NEXT_CHUNK_PTR_SIZE, 2258c2ecf20Sopenharmony_ci &curr->dma_addr, GFP_KERNEL); 2268c2ecf20Sopenharmony_ci if (!curr->head) { 2278c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 2288c2ecf20Sopenharmony_ci "Command Q (%d) chunk (%d) allocation failed\n", 2298c2ecf20Sopenharmony_ci i, queue->num_chunks); 2308c2ecf20Sopenharmony_ci goto free_curr; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci curr->size = c_size; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (queue->num_chunks == 0) { 2358c2ecf20Sopenharmony_ci first = curr; 2368c2ecf20Sopenharmony_ci queue->base = first; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci list_add_tail(&curr->nextchunk, 2398c2ecf20Sopenharmony_ci &cqinfo->queue[i].chead); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci queue->num_chunks++; 2428c2ecf20Sopenharmony_ci rem_q_size -= c_size; 2438c2ecf20Sopenharmony_ci if (last) 2448c2ecf20Sopenharmony_ci *((u64 *)(&last->head[last->size])) = 2458c2ecf20Sopenharmony_ci (u64)curr->dma_addr; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci last = curr; 2488c2ecf20Sopenharmony_ci } while (rem_q_size); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* 2518c2ecf20Sopenharmony_ci * Make the queue circular, tie back last chunk entry to head 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_ci curr = first; 2548c2ecf20Sopenharmony_ci *((u64 *)(&last->head[last->size])) = (u64)curr->dma_addr; 2558c2ecf20Sopenharmony_ci queue->qhead = curr; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci return 0; 2588c2ecf20Sopenharmony_cifree_curr: 2598c2ecf20Sopenharmony_ci kfree(curr); 2608c2ecf20Sopenharmony_cicmd_qfail: 2618c2ecf20Sopenharmony_ci free_command_queues(cptvf, cqinfo); 2628c2ecf20Sopenharmony_ci return -ENOMEM; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_cistatic int init_command_queues(struct otx_cptvf *cptvf, u32 qlen) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 2688c2ecf20Sopenharmony_ci int ret; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci /* setup command queues */ 2718c2ecf20Sopenharmony_ci ret = alloc_command_queues(cptvf, &cptvf->cqinfo, qlen); 2728c2ecf20Sopenharmony_ci if (ret) { 2738c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to allocate command queues (%u)\n", 2748c2ecf20Sopenharmony_ci cptvf->num_queues); 2758c2ecf20Sopenharmony_ci return ret; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci return ret; 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_cistatic void cleanup_command_queues(struct otx_cptvf *cptvf) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci if (!cptvf->num_queues) 2858c2ecf20Sopenharmony_ci return; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci dev_dbg(&pdev->dev, "Cleaning VQ command queue (%u)\n", 2888c2ecf20Sopenharmony_ci cptvf->num_queues); 2898c2ecf20Sopenharmony_ci free_command_queues(cptvf, &cptvf->cqinfo); 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic void cptvf_sw_cleanup(struct otx_cptvf *cptvf) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci cleanup_worker_threads(cptvf); 2958c2ecf20Sopenharmony_ci cleanup_pending_queues(cptvf); 2968c2ecf20Sopenharmony_ci cleanup_command_queues(cptvf); 2978c2ecf20Sopenharmony_ci} 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic int cptvf_sw_init(struct otx_cptvf *cptvf, u32 qlen, u32 num_queues) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 3028c2ecf20Sopenharmony_ci u32 max_dev_queues = 0; 3038c2ecf20Sopenharmony_ci int ret; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci max_dev_queues = OTX_CPT_NUM_QS_PER_VF; 3068c2ecf20Sopenharmony_ci /* possible cpus */ 3078c2ecf20Sopenharmony_ci num_queues = min_t(u32, num_queues, max_dev_queues); 3088c2ecf20Sopenharmony_ci cptvf->num_queues = num_queues; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci ret = init_command_queues(cptvf, qlen); 3118c2ecf20Sopenharmony_ci if (ret) { 3128c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to setup command queues (%u)\n", 3138c2ecf20Sopenharmony_ci num_queues); 3148c2ecf20Sopenharmony_ci return ret; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci ret = init_pending_queues(cptvf, qlen, num_queues); 3188c2ecf20Sopenharmony_ci if (ret) { 3198c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to setup pending queues (%u)\n", 3208c2ecf20Sopenharmony_ci num_queues); 3218c2ecf20Sopenharmony_ci goto setup_pqfail; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci /* Create worker threads for BH processing */ 3258c2ecf20Sopenharmony_ci ret = init_worker_threads(cptvf); 3268c2ecf20Sopenharmony_ci if (ret) { 3278c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to setup worker threads\n"); 3288c2ecf20Sopenharmony_ci goto init_work_fail; 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci return 0; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ciinit_work_fail: 3338c2ecf20Sopenharmony_ci cleanup_worker_threads(cptvf); 3348c2ecf20Sopenharmony_ci cleanup_pending_queues(cptvf); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cisetup_pqfail: 3378c2ecf20Sopenharmony_ci cleanup_command_queues(cptvf); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci return ret; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic void cptvf_free_irq_affinity(struct otx_cptvf *cptvf, int vec) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci irq_set_affinity_hint(pci_irq_vector(cptvf->pdev, vec), NULL); 3458c2ecf20Sopenharmony_ci free_cpumask_var(cptvf->affinity_mask[vec]); 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic void cptvf_write_vq_ctl(struct otx_cptvf *cptvf, bool val) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci union otx_cptx_vqx_ctl vqx_ctl; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci vqx_ctl.u = readq(cptvf->reg_base + OTX_CPT_VQX_CTL(0)); 3538c2ecf20Sopenharmony_ci vqx_ctl.s.ena = val; 3548c2ecf20Sopenharmony_ci writeq(vqx_ctl.u, cptvf->reg_base + OTX_CPT_VQX_CTL(0)); 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_civoid otx_cptvf_write_vq_doorbell(struct otx_cptvf *cptvf, u32 val) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci union otx_cptx_vqx_doorbell vqx_dbell; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci vqx_dbell.u = readq(cptvf->reg_base + OTX_CPT_VQX_DOORBELL(0)); 3628c2ecf20Sopenharmony_ci vqx_dbell.s.dbell_cnt = val * 8; /* Num of Instructions * 8 words */ 3638c2ecf20Sopenharmony_ci writeq(vqx_dbell.u, cptvf->reg_base + OTX_CPT_VQX_DOORBELL(0)); 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistatic void cptvf_write_vq_inprog(struct otx_cptvf *cptvf, u8 val) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci union otx_cptx_vqx_inprog vqx_inprg; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci vqx_inprg.u = readq(cptvf->reg_base + OTX_CPT_VQX_INPROG(0)); 3718c2ecf20Sopenharmony_ci vqx_inprg.s.inflight = val; 3728c2ecf20Sopenharmony_ci writeq(vqx_inprg.u, cptvf->reg_base + OTX_CPT_VQX_INPROG(0)); 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic void cptvf_write_vq_done_numwait(struct otx_cptvf *cptvf, u32 val) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci union otx_cptx_vqx_done_wait vqx_dwait; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci vqx_dwait.u = readq(cptvf->reg_base + OTX_CPT_VQX_DONE_WAIT(0)); 3808c2ecf20Sopenharmony_ci vqx_dwait.s.num_wait = val; 3818c2ecf20Sopenharmony_ci writeq(vqx_dwait.u, cptvf->reg_base + OTX_CPT_VQX_DONE_WAIT(0)); 3828c2ecf20Sopenharmony_ci} 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cistatic u32 cptvf_read_vq_done_numwait(struct otx_cptvf *cptvf) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci union otx_cptx_vqx_done_wait vqx_dwait; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci vqx_dwait.u = readq(cptvf->reg_base + OTX_CPT_VQX_DONE_WAIT(0)); 3898c2ecf20Sopenharmony_ci return vqx_dwait.s.num_wait; 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic void cptvf_write_vq_done_timewait(struct otx_cptvf *cptvf, u16 time) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci union otx_cptx_vqx_done_wait vqx_dwait; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci vqx_dwait.u = readq(cptvf->reg_base + OTX_CPT_VQX_DONE_WAIT(0)); 3978c2ecf20Sopenharmony_ci vqx_dwait.s.time_wait = time; 3988c2ecf20Sopenharmony_ci writeq(vqx_dwait.u, cptvf->reg_base + OTX_CPT_VQX_DONE_WAIT(0)); 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic u16 cptvf_read_vq_done_timewait(struct otx_cptvf *cptvf) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci union otx_cptx_vqx_done_wait vqx_dwait; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci vqx_dwait.u = readq(cptvf->reg_base + OTX_CPT_VQX_DONE_WAIT(0)); 4078c2ecf20Sopenharmony_ci return vqx_dwait.s.time_wait; 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic void cptvf_enable_swerr_interrupts(struct otx_cptvf *cptvf) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci union otx_cptx_vqx_misc_ena_w1s vqx_misc_ena; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci vqx_misc_ena.u = readq(cptvf->reg_base + OTX_CPT_VQX_MISC_ENA_W1S(0)); 4158c2ecf20Sopenharmony_ci /* Enable SWERR interrupts for the requested VF */ 4168c2ecf20Sopenharmony_ci vqx_misc_ena.s.swerr = 1; 4178c2ecf20Sopenharmony_ci writeq(vqx_misc_ena.u, cptvf->reg_base + OTX_CPT_VQX_MISC_ENA_W1S(0)); 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic void cptvf_enable_mbox_interrupts(struct otx_cptvf *cptvf) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci union otx_cptx_vqx_misc_ena_w1s vqx_misc_ena; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci vqx_misc_ena.u = readq(cptvf->reg_base + OTX_CPT_VQX_MISC_ENA_W1S(0)); 4258c2ecf20Sopenharmony_ci /* Enable MBOX interrupt for the requested VF */ 4268c2ecf20Sopenharmony_ci vqx_misc_ena.s.mbox = 1; 4278c2ecf20Sopenharmony_ci writeq(vqx_misc_ena.u, cptvf->reg_base + OTX_CPT_VQX_MISC_ENA_W1S(0)); 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic void cptvf_enable_done_interrupts(struct otx_cptvf *cptvf) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci union otx_cptx_vqx_done_ena_w1s vqx_done_ena; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci vqx_done_ena.u = readq(cptvf->reg_base + OTX_CPT_VQX_DONE_ENA_W1S(0)); 4358c2ecf20Sopenharmony_ci /* Enable DONE interrupt for the requested VF */ 4368c2ecf20Sopenharmony_ci vqx_done_ena.s.done = 1; 4378c2ecf20Sopenharmony_ci writeq(vqx_done_ena.u, cptvf->reg_base + OTX_CPT_VQX_DONE_ENA_W1S(0)); 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_cistatic void cptvf_clear_dovf_intr(struct otx_cptvf *cptvf) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci union otx_cptx_vqx_misc_int vqx_misc_int; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci vqx_misc_int.u = readq(cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4458c2ecf20Sopenharmony_ci /* W1C for the VF */ 4468c2ecf20Sopenharmony_ci vqx_misc_int.s.dovf = 1; 4478c2ecf20Sopenharmony_ci writeq(vqx_misc_int.u, cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic void cptvf_clear_irde_intr(struct otx_cptvf *cptvf) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci union otx_cptx_vqx_misc_int vqx_misc_int; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci vqx_misc_int.u = readq(cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4558c2ecf20Sopenharmony_ci /* W1C for the VF */ 4568c2ecf20Sopenharmony_ci vqx_misc_int.s.irde = 1; 4578c2ecf20Sopenharmony_ci writeq(vqx_misc_int.u, cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4588c2ecf20Sopenharmony_ci} 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_cistatic void cptvf_clear_nwrp_intr(struct otx_cptvf *cptvf) 4618c2ecf20Sopenharmony_ci{ 4628c2ecf20Sopenharmony_ci union otx_cptx_vqx_misc_int vqx_misc_int; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci vqx_misc_int.u = readq(cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4658c2ecf20Sopenharmony_ci /* W1C for the VF */ 4668c2ecf20Sopenharmony_ci vqx_misc_int.s.nwrp = 1; 4678c2ecf20Sopenharmony_ci writeq(vqx_misc_int.u, cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_cistatic void cptvf_clear_mbox_intr(struct otx_cptvf *cptvf) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci union otx_cptx_vqx_misc_int vqx_misc_int; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci vqx_misc_int.u = readq(cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4758c2ecf20Sopenharmony_ci /* W1C for the VF */ 4768c2ecf20Sopenharmony_ci vqx_misc_int.s.mbox = 1; 4778c2ecf20Sopenharmony_ci writeq(vqx_misc_int.u, cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_cistatic void cptvf_clear_swerr_intr(struct otx_cptvf *cptvf) 4818c2ecf20Sopenharmony_ci{ 4828c2ecf20Sopenharmony_ci union otx_cptx_vqx_misc_int vqx_misc_int; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci vqx_misc_int.u = readq(cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4858c2ecf20Sopenharmony_ci /* W1C for the VF */ 4868c2ecf20Sopenharmony_ci vqx_misc_int.s.swerr = 1; 4878c2ecf20Sopenharmony_ci writeq(vqx_misc_int.u, cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4888c2ecf20Sopenharmony_ci} 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_cistatic u64 cptvf_read_vf_misc_intr_status(struct otx_cptvf *cptvf) 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci return readq(cptvf->reg_base + OTX_CPT_VQX_MISC_INT(0)); 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_cistatic irqreturn_t cptvf_misc_intr_handler(int __always_unused irq, 4968c2ecf20Sopenharmony_ci void *arg) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf = arg; 4998c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 5008c2ecf20Sopenharmony_ci u64 intr; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci intr = cptvf_read_vf_misc_intr_status(cptvf); 5038c2ecf20Sopenharmony_ci /* Check for MISC interrupt types */ 5048c2ecf20Sopenharmony_ci if (likely(intr & OTX_CPT_VF_INTR_MBOX_MASK)) { 5058c2ecf20Sopenharmony_ci dev_dbg(&pdev->dev, "Mailbox interrupt 0x%llx on CPT VF %d\n", 5068c2ecf20Sopenharmony_ci intr, cptvf->vfid); 5078c2ecf20Sopenharmony_ci otx_cptvf_handle_mbox_intr(cptvf); 5088c2ecf20Sopenharmony_ci cptvf_clear_mbox_intr(cptvf); 5098c2ecf20Sopenharmony_ci } else if (unlikely(intr & OTX_CPT_VF_INTR_DOVF_MASK)) { 5108c2ecf20Sopenharmony_ci cptvf_clear_dovf_intr(cptvf); 5118c2ecf20Sopenharmony_ci /* Clear doorbell count */ 5128c2ecf20Sopenharmony_ci otx_cptvf_write_vq_doorbell(cptvf, 0); 5138c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 5148c2ecf20Sopenharmony_ci "Doorbell overflow error interrupt 0x%llx on CPT VF %d\n", 5158c2ecf20Sopenharmony_ci intr, cptvf->vfid); 5168c2ecf20Sopenharmony_ci } else if (unlikely(intr & OTX_CPT_VF_INTR_IRDE_MASK)) { 5178c2ecf20Sopenharmony_ci cptvf_clear_irde_intr(cptvf); 5188c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 5198c2ecf20Sopenharmony_ci "Instruction NCB read error interrupt 0x%llx on CPT VF %d\n", 5208c2ecf20Sopenharmony_ci intr, cptvf->vfid); 5218c2ecf20Sopenharmony_ci } else if (unlikely(intr & OTX_CPT_VF_INTR_NWRP_MASK)) { 5228c2ecf20Sopenharmony_ci cptvf_clear_nwrp_intr(cptvf); 5238c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 5248c2ecf20Sopenharmony_ci "NCB response write error interrupt 0x%llx on CPT VF %d\n", 5258c2ecf20Sopenharmony_ci intr, cptvf->vfid); 5268c2ecf20Sopenharmony_ci } else if (unlikely(intr & OTX_CPT_VF_INTR_SERR_MASK)) { 5278c2ecf20Sopenharmony_ci cptvf_clear_swerr_intr(cptvf); 5288c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 5298c2ecf20Sopenharmony_ci "Software error interrupt 0x%llx on CPT VF %d\n", 5308c2ecf20Sopenharmony_ci intr, cptvf->vfid); 5318c2ecf20Sopenharmony_ci } else { 5328c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unhandled interrupt in OTX_CPT VF %d\n", 5338c2ecf20Sopenharmony_ci cptvf->vfid); 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci return IRQ_HANDLED; 5378c2ecf20Sopenharmony_ci} 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_cistatic inline struct otx_cptvf_wqe *get_cptvf_vq_wqe(struct otx_cptvf *cptvf, 5408c2ecf20Sopenharmony_ci int qno) 5418c2ecf20Sopenharmony_ci{ 5428c2ecf20Sopenharmony_ci struct otx_cptvf_wqe_info *nwqe_info; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci if (unlikely(qno >= cptvf->num_queues)) 5458c2ecf20Sopenharmony_ci return NULL; 5468c2ecf20Sopenharmony_ci nwqe_info = (struct otx_cptvf_wqe_info *)cptvf->wqe_info; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci return &nwqe_info->vq_wqe[qno]; 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_cistatic inline u32 cptvf_read_vq_done_count(struct otx_cptvf *cptvf) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci union otx_cptx_vqx_done vqx_done; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci vqx_done.u = readq(cptvf->reg_base + OTX_CPT_VQX_DONE(0)); 5568c2ecf20Sopenharmony_ci return vqx_done.s.done; 5578c2ecf20Sopenharmony_ci} 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_cistatic inline void cptvf_write_vq_done_ack(struct otx_cptvf *cptvf, 5608c2ecf20Sopenharmony_ci u32 ackcnt) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci union otx_cptx_vqx_done_ack vqx_dack_cnt; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci vqx_dack_cnt.u = readq(cptvf->reg_base + OTX_CPT_VQX_DONE_ACK(0)); 5658c2ecf20Sopenharmony_ci vqx_dack_cnt.s.done_ack = ackcnt; 5668c2ecf20Sopenharmony_ci writeq(vqx_dack_cnt.u, cptvf->reg_base + OTX_CPT_VQX_DONE_ACK(0)); 5678c2ecf20Sopenharmony_ci} 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_cistatic irqreturn_t cptvf_done_intr_handler(int __always_unused irq, 5708c2ecf20Sopenharmony_ci void *cptvf_dev) 5718c2ecf20Sopenharmony_ci{ 5728c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf = (struct otx_cptvf *)cptvf_dev; 5738c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 5748c2ecf20Sopenharmony_ci /* Read the number of completions */ 5758c2ecf20Sopenharmony_ci u32 intr = cptvf_read_vq_done_count(cptvf); 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci if (intr) { 5788c2ecf20Sopenharmony_ci struct otx_cptvf_wqe *wqe; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci /* 5818c2ecf20Sopenharmony_ci * Acknowledge the number of scheduled completions for 5828c2ecf20Sopenharmony_ci * processing 5838c2ecf20Sopenharmony_ci */ 5848c2ecf20Sopenharmony_ci cptvf_write_vq_done_ack(cptvf, intr); 5858c2ecf20Sopenharmony_ci wqe = get_cptvf_vq_wqe(cptvf, 0); 5868c2ecf20Sopenharmony_ci if (unlikely(!wqe)) { 5878c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "No work to schedule for VF (%d)\n", 5888c2ecf20Sopenharmony_ci cptvf->vfid); 5898c2ecf20Sopenharmony_ci return IRQ_NONE; 5908c2ecf20Sopenharmony_ci } 5918c2ecf20Sopenharmony_ci tasklet_hi_schedule(&wqe->twork); 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci return IRQ_HANDLED; 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic void cptvf_set_irq_affinity(struct otx_cptvf *cptvf, int vec) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 6008c2ecf20Sopenharmony_ci int cpu; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci if (!zalloc_cpumask_var(&cptvf->affinity_mask[vec], 6038c2ecf20Sopenharmony_ci GFP_KERNEL)) { 6048c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 6058c2ecf20Sopenharmony_ci "Allocation failed for affinity_mask for VF %d\n", 6068c2ecf20Sopenharmony_ci cptvf->vfid); 6078c2ecf20Sopenharmony_ci return; 6088c2ecf20Sopenharmony_ci } 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci cpu = cptvf->vfid % num_online_cpus(); 6118c2ecf20Sopenharmony_ci cpumask_set_cpu(cpumask_local_spread(cpu, cptvf->node), 6128c2ecf20Sopenharmony_ci cptvf->affinity_mask[vec]); 6138c2ecf20Sopenharmony_ci irq_set_affinity_hint(pci_irq_vector(pdev, vec), 6148c2ecf20Sopenharmony_ci cptvf->affinity_mask[vec]); 6158c2ecf20Sopenharmony_ci} 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_cistatic void cptvf_write_vq_saddr(struct otx_cptvf *cptvf, u64 val) 6188c2ecf20Sopenharmony_ci{ 6198c2ecf20Sopenharmony_ci union otx_cptx_vqx_saddr vqx_saddr; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci vqx_saddr.u = val; 6228c2ecf20Sopenharmony_ci writeq(vqx_saddr.u, cptvf->reg_base + OTX_CPT_VQX_SADDR(0)); 6238c2ecf20Sopenharmony_ci} 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_cistatic void cptvf_device_init(struct otx_cptvf *cptvf) 6268c2ecf20Sopenharmony_ci{ 6278c2ecf20Sopenharmony_ci u64 base_addr = 0; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci /* Disable the VQ */ 6308c2ecf20Sopenharmony_ci cptvf_write_vq_ctl(cptvf, 0); 6318c2ecf20Sopenharmony_ci /* Reset the doorbell */ 6328c2ecf20Sopenharmony_ci otx_cptvf_write_vq_doorbell(cptvf, 0); 6338c2ecf20Sopenharmony_ci /* Clear inflight */ 6348c2ecf20Sopenharmony_ci cptvf_write_vq_inprog(cptvf, 0); 6358c2ecf20Sopenharmony_ci /* Write VQ SADDR */ 6368c2ecf20Sopenharmony_ci base_addr = (u64)(cptvf->cqinfo.queue[0].qhead->dma_addr); 6378c2ecf20Sopenharmony_ci cptvf_write_vq_saddr(cptvf, base_addr); 6388c2ecf20Sopenharmony_ci /* Configure timerhold / coalescence */ 6398c2ecf20Sopenharmony_ci cptvf_write_vq_done_timewait(cptvf, OTX_CPT_TIMER_HOLD); 6408c2ecf20Sopenharmony_ci cptvf_write_vq_done_numwait(cptvf, OTX_CPT_COUNT_HOLD); 6418c2ecf20Sopenharmony_ci /* Enable the VQ */ 6428c2ecf20Sopenharmony_ci cptvf_write_vq_ctl(cptvf, 1); 6438c2ecf20Sopenharmony_ci /* Flag the VF ready */ 6448c2ecf20Sopenharmony_ci cptvf->flags |= OTX_CPT_FLAG_DEVICE_READY; 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic ssize_t vf_type_show(struct device *dev, 6488c2ecf20Sopenharmony_ci struct device_attribute *attr, 6498c2ecf20Sopenharmony_ci char *buf) 6508c2ecf20Sopenharmony_ci{ 6518c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf = dev_get_drvdata(dev); 6528c2ecf20Sopenharmony_ci char *msg; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci switch (cptvf->vftype) { 6558c2ecf20Sopenharmony_ci case OTX_CPT_AE_TYPES: 6568c2ecf20Sopenharmony_ci msg = "AE"; 6578c2ecf20Sopenharmony_ci break; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci case OTX_CPT_SE_TYPES: 6608c2ecf20Sopenharmony_ci msg = "SE"; 6618c2ecf20Sopenharmony_ci break; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci default: 6648c2ecf20Sopenharmony_ci msg = "Invalid"; 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s\n", msg); 6688c2ecf20Sopenharmony_ci} 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_cistatic ssize_t vf_engine_group_show(struct device *dev, 6718c2ecf20Sopenharmony_ci struct device_attribute *attr, 6728c2ecf20Sopenharmony_ci char *buf) 6738c2ecf20Sopenharmony_ci{ 6748c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf = dev_get_drvdata(dev); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", cptvf->vfgrp); 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic ssize_t vf_engine_group_store(struct device *dev, 6808c2ecf20Sopenharmony_ci struct device_attribute *attr, 6818c2ecf20Sopenharmony_ci const char *buf, size_t count) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf = dev_get_drvdata(dev); 6848c2ecf20Sopenharmony_ci int val, ret; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci ret = kstrtoint(buf, 10, &val); 6878c2ecf20Sopenharmony_ci if (ret) 6888c2ecf20Sopenharmony_ci return ret; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci if (val < 0) 6918c2ecf20Sopenharmony_ci return -EINVAL; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci if (val >= OTX_CPT_MAX_ENGINE_GROUPS) { 6948c2ecf20Sopenharmony_ci dev_err(dev, "Engine group >= than max available groups %d\n", 6958c2ecf20Sopenharmony_ci OTX_CPT_MAX_ENGINE_GROUPS); 6968c2ecf20Sopenharmony_ci return -EINVAL; 6978c2ecf20Sopenharmony_ci } 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci ret = otx_cptvf_send_vf_to_grp_msg(cptvf, val); 7008c2ecf20Sopenharmony_ci if (ret) 7018c2ecf20Sopenharmony_ci return ret; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci return count; 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_cistatic ssize_t vf_coalesc_time_wait_show(struct device *dev, 7078c2ecf20Sopenharmony_ci struct device_attribute *attr, 7088c2ecf20Sopenharmony_ci char *buf) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf = dev_get_drvdata(dev); 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 7138c2ecf20Sopenharmony_ci cptvf_read_vq_done_timewait(cptvf)); 7148c2ecf20Sopenharmony_ci} 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_cistatic ssize_t vf_coalesc_num_wait_show(struct device *dev, 7178c2ecf20Sopenharmony_ci struct device_attribute *attr, 7188c2ecf20Sopenharmony_ci char *buf) 7198c2ecf20Sopenharmony_ci{ 7208c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf = dev_get_drvdata(dev); 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", 7238c2ecf20Sopenharmony_ci cptvf_read_vq_done_numwait(cptvf)); 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic ssize_t vf_coalesc_time_wait_store(struct device *dev, 7278c2ecf20Sopenharmony_ci struct device_attribute *attr, 7288c2ecf20Sopenharmony_ci const char *buf, size_t count) 7298c2ecf20Sopenharmony_ci{ 7308c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf = dev_get_drvdata(dev); 7318c2ecf20Sopenharmony_ci long val; 7328c2ecf20Sopenharmony_ci int ret; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci ret = kstrtol(buf, 10, &val); 7358c2ecf20Sopenharmony_ci if (ret != 0) 7368c2ecf20Sopenharmony_ci return ret; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci if (val < OTX_CPT_COALESC_MIN_TIME_WAIT || 7398c2ecf20Sopenharmony_ci val > OTX_CPT_COALESC_MAX_TIME_WAIT) 7408c2ecf20Sopenharmony_ci return -EINVAL; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci cptvf_write_vq_done_timewait(cptvf, val); 7438c2ecf20Sopenharmony_ci return count; 7448c2ecf20Sopenharmony_ci} 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_cistatic ssize_t vf_coalesc_num_wait_store(struct device *dev, 7478c2ecf20Sopenharmony_ci struct device_attribute *attr, 7488c2ecf20Sopenharmony_ci const char *buf, size_t count) 7498c2ecf20Sopenharmony_ci{ 7508c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf = dev_get_drvdata(dev); 7518c2ecf20Sopenharmony_ci long val; 7528c2ecf20Sopenharmony_ci int ret; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci ret = kstrtol(buf, 10, &val); 7558c2ecf20Sopenharmony_ci if (ret != 0) 7568c2ecf20Sopenharmony_ci return ret; 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci if (val < OTX_CPT_COALESC_MIN_NUM_WAIT || 7598c2ecf20Sopenharmony_ci val > OTX_CPT_COALESC_MAX_NUM_WAIT) 7608c2ecf20Sopenharmony_ci return -EINVAL; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci cptvf_write_vq_done_numwait(cptvf, val); 7638c2ecf20Sopenharmony_ci return count; 7648c2ecf20Sopenharmony_ci} 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(vf_type); 7678c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(vf_engine_group); 7688c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(vf_coalesc_time_wait); 7698c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(vf_coalesc_num_wait); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_cistatic struct attribute *otx_cptvf_attrs[] = { 7728c2ecf20Sopenharmony_ci &dev_attr_vf_type.attr, 7738c2ecf20Sopenharmony_ci &dev_attr_vf_engine_group.attr, 7748c2ecf20Sopenharmony_ci &dev_attr_vf_coalesc_time_wait.attr, 7758c2ecf20Sopenharmony_ci &dev_attr_vf_coalesc_num_wait.attr, 7768c2ecf20Sopenharmony_ci NULL 7778c2ecf20Sopenharmony_ci}; 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_cistatic const struct attribute_group otx_cptvf_sysfs_group = { 7808c2ecf20Sopenharmony_ci .attrs = otx_cptvf_attrs, 7818c2ecf20Sopenharmony_ci}; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_cistatic int otx_cptvf_probe(struct pci_dev *pdev, 7848c2ecf20Sopenharmony_ci const struct pci_device_id *ent) 7858c2ecf20Sopenharmony_ci{ 7868c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 7878c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf; 7888c2ecf20Sopenharmony_ci int err; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci cptvf = devm_kzalloc(dev, sizeof(*cptvf), GFP_KERNEL); 7918c2ecf20Sopenharmony_ci if (!cptvf) 7928c2ecf20Sopenharmony_ci return -ENOMEM; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, cptvf); 7958c2ecf20Sopenharmony_ci cptvf->pdev = pdev; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci err = pci_enable_device(pdev); 7988c2ecf20Sopenharmony_ci if (err) { 7998c2ecf20Sopenharmony_ci dev_err(dev, "Failed to enable PCI device\n"); 8008c2ecf20Sopenharmony_ci goto clear_drvdata; 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci err = pci_request_regions(pdev, DRV_NAME); 8038c2ecf20Sopenharmony_ci if (err) { 8048c2ecf20Sopenharmony_ci dev_err(dev, "PCI request regions failed 0x%x\n", err); 8058c2ecf20Sopenharmony_ci goto disable_device; 8068c2ecf20Sopenharmony_ci } 8078c2ecf20Sopenharmony_ci err = pci_set_dma_mask(pdev, DMA_BIT_MASK(48)); 8088c2ecf20Sopenharmony_ci if (err) { 8098c2ecf20Sopenharmony_ci dev_err(dev, "Unable to get usable DMA configuration\n"); 8108c2ecf20Sopenharmony_ci goto release_regions; 8118c2ecf20Sopenharmony_ci } 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(48)); 8148c2ecf20Sopenharmony_ci if (err) { 8158c2ecf20Sopenharmony_ci dev_err(dev, "Unable to get 48-bit DMA for consistent allocations\n"); 8168c2ecf20Sopenharmony_ci goto release_regions; 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci /* MAP PF's configuration registers */ 8208c2ecf20Sopenharmony_ci cptvf->reg_base = pci_iomap(pdev, OTX_CPT_VF_PCI_CFG_BAR, 0); 8218c2ecf20Sopenharmony_ci if (!cptvf->reg_base) { 8228c2ecf20Sopenharmony_ci dev_err(dev, "Cannot map config register space, aborting\n"); 8238c2ecf20Sopenharmony_ci err = -ENOMEM; 8248c2ecf20Sopenharmony_ci goto release_regions; 8258c2ecf20Sopenharmony_ci } 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci cptvf->node = dev_to_node(&pdev->dev); 8288c2ecf20Sopenharmony_ci err = pci_alloc_irq_vectors(pdev, OTX_CPT_VF_MSIX_VECTORS, 8298c2ecf20Sopenharmony_ci OTX_CPT_VF_MSIX_VECTORS, PCI_IRQ_MSIX); 8308c2ecf20Sopenharmony_ci if (err < 0) { 8318c2ecf20Sopenharmony_ci dev_err(dev, "Request for #%d msix vectors failed\n", 8328c2ecf20Sopenharmony_ci OTX_CPT_VF_MSIX_VECTORS); 8338c2ecf20Sopenharmony_ci goto unmap_region; 8348c2ecf20Sopenharmony_ci } 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci err = request_irq(pci_irq_vector(pdev, CPT_VF_INT_VEC_E_MISC), 8378c2ecf20Sopenharmony_ci cptvf_misc_intr_handler, 0, "CPT VF misc intr", 8388c2ecf20Sopenharmony_ci cptvf); 8398c2ecf20Sopenharmony_ci if (err) { 8408c2ecf20Sopenharmony_ci dev_err(dev, "Failed to request misc irq\n"); 8418c2ecf20Sopenharmony_ci goto free_vectors; 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci /* Enable mailbox interrupt */ 8458c2ecf20Sopenharmony_ci cptvf_enable_mbox_interrupts(cptvf); 8468c2ecf20Sopenharmony_ci cptvf_enable_swerr_interrupts(cptvf); 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci /* Check cpt pf status, gets chip ID / device Id from PF if ready */ 8498c2ecf20Sopenharmony_ci err = otx_cptvf_check_pf_ready(cptvf); 8508c2ecf20Sopenharmony_ci if (err) 8518c2ecf20Sopenharmony_ci goto free_misc_irq; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci /* CPT VF software resources initialization */ 8548c2ecf20Sopenharmony_ci cptvf->cqinfo.qchunksize = OTX_CPT_CMD_QCHUNK_SIZE; 8558c2ecf20Sopenharmony_ci err = cptvf_sw_init(cptvf, OTX_CPT_CMD_QLEN, OTX_CPT_NUM_QS_PER_VF); 8568c2ecf20Sopenharmony_ci if (err) { 8578c2ecf20Sopenharmony_ci dev_err(dev, "cptvf_sw_init() failed\n"); 8588c2ecf20Sopenharmony_ci goto free_misc_irq; 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci /* Convey VQ LEN to PF */ 8618c2ecf20Sopenharmony_ci err = otx_cptvf_send_vq_size_msg(cptvf); 8628c2ecf20Sopenharmony_ci if (err) 8638c2ecf20Sopenharmony_ci goto sw_cleanup; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci /* CPT VF device initialization */ 8668c2ecf20Sopenharmony_ci cptvf_device_init(cptvf); 8678c2ecf20Sopenharmony_ci /* Send msg to PF to assign currnet Q to required group */ 8688c2ecf20Sopenharmony_ci err = otx_cptvf_send_vf_to_grp_msg(cptvf, cptvf->vfgrp); 8698c2ecf20Sopenharmony_ci if (err) 8708c2ecf20Sopenharmony_ci goto sw_cleanup; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci cptvf->priority = 1; 8738c2ecf20Sopenharmony_ci err = otx_cptvf_send_vf_priority_msg(cptvf); 8748c2ecf20Sopenharmony_ci if (err) 8758c2ecf20Sopenharmony_ci goto sw_cleanup; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci err = request_irq(pci_irq_vector(pdev, CPT_VF_INT_VEC_E_DONE), 8788c2ecf20Sopenharmony_ci cptvf_done_intr_handler, 0, "CPT VF done intr", 8798c2ecf20Sopenharmony_ci cptvf); 8808c2ecf20Sopenharmony_ci if (err) { 8818c2ecf20Sopenharmony_ci dev_err(dev, "Failed to request done irq\n"); 8828c2ecf20Sopenharmony_ci goto free_done_irq; 8838c2ecf20Sopenharmony_ci } 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci /* Enable done interrupt */ 8868c2ecf20Sopenharmony_ci cptvf_enable_done_interrupts(cptvf); 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci /* Set irq affinity masks */ 8898c2ecf20Sopenharmony_ci cptvf_set_irq_affinity(cptvf, CPT_VF_INT_VEC_E_MISC); 8908c2ecf20Sopenharmony_ci cptvf_set_irq_affinity(cptvf, CPT_VF_INT_VEC_E_DONE); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci err = otx_cptvf_send_vf_up(cptvf); 8938c2ecf20Sopenharmony_ci if (err) 8948c2ecf20Sopenharmony_ci goto free_irq_affinity; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci /* Initialize algorithms and set ops */ 8978c2ecf20Sopenharmony_ci err = otx_cpt_crypto_init(pdev, THIS_MODULE, 8988c2ecf20Sopenharmony_ci cptvf->vftype == OTX_CPT_SE_TYPES ? OTX_CPT_SE : OTX_CPT_AE, 8998c2ecf20Sopenharmony_ci cptvf->vftype, 1, cptvf->num_vfs); 9008c2ecf20Sopenharmony_ci if (err) { 9018c2ecf20Sopenharmony_ci dev_err(dev, "Failed to register crypto algs\n"); 9028c2ecf20Sopenharmony_ci goto free_irq_affinity; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci err = sysfs_create_group(&dev->kobj, &otx_cptvf_sysfs_group); 9068c2ecf20Sopenharmony_ci if (err) { 9078c2ecf20Sopenharmony_ci dev_err(dev, "Creating sysfs entries failed\n"); 9088c2ecf20Sopenharmony_ci goto crypto_exit; 9098c2ecf20Sopenharmony_ci } 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci return 0; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_cicrypto_exit: 9148c2ecf20Sopenharmony_ci otx_cpt_crypto_exit(pdev, THIS_MODULE, cptvf->vftype); 9158c2ecf20Sopenharmony_cifree_irq_affinity: 9168c2ecf20Sopenharmony_ci cptvf_free_irq_affinity(cptvf, CPT_VF_INT_VEC_E_DONE); 9178c2ecf20Sopenharmony_ci cptvf_free_irq_affinity(cptvf, CPT_VF_INT_VEC_E_MISC); 9188c2ecf20Sopenharmony_cifree_done_irq: 9198c2ecf20Sopenharmony_ci free_irq(pci_irq_vector(pdev, CPT_VF_INT_VEC_E_DONE), cptvf); 9208c2ecf20Sopenharmony_cisw_cleanup: 9218c2ecf20Sopenharmony_ci cptvf_sw_cleanup(cptvf); 9228c2ecf20Sopenharmony_cifree_misc_irq: 9238c2ecf20Sopenharmony_ci free_irq(pci_irq_vector(pdev, CPT_VF_INT_VEC_E_MISC), cptvf); 9248c2ecf20Sopenharmony_cifree_vectors: 9258c2ecf20Sopenharmony_ci pci_free_irq_vectors(cptvf->pdev); 9268c2ecf20Sopenharmony_ciunmap_region: 9278c2ecf20Sopenharmony_ci pci_iounmap(pdev, cptvf->reg_base); 9288c2ecf20Sopenharmony_cirelease_regions: 9298c2ecf20Sopenharmony_ci pci_release_regions(pdev); 9308c2ecf20Sopenharmony_cidisable_device: 9318c2ecf20Sopenharmony_ci pci_disable_device(pdev); 9328c2ecf20Sopenharmony_ciclear_drvdata: 9338c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, NULL); 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci return err; 9368c2ecf20Sopenharmony_ci} 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_cistatic void otx_cptvf_remove(struct pci_dev *pdev) 9398c2ecf20Sopenharmony_ci{ 9408c2ecf20Sopenharmony_ci struct otx_cptvf *cptvf = pci_get_drvdata(pdev); 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci if (!cptvf) { 9438c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Invalid CPT-VF device\n"); 9448c2ecf20Sopenharmony_ci return; 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci /* Convey DOWN to PF */ 9488c2ecf20Sopenharmony_ci if (otx_cptvf_send_vf_down(cptvf)) { 9498c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "PF not responding to DOWN msg\n"); 9508c2ecf20Sopenharmony_ci } else { 9518c2ecf20Sopenharmony_ci sysfs_remove_group(&pdev->dev.kobj, &otx_cptvf_sysfs_group); 9528c2ecf20Sopenharmony_ci otx_cpt_crypto_exit(pdev, THIS_MODULE, cptvf->vftype); 9538c2ecf20Sopenharmony_ci cptvf_free_irq_affinity(cptvf, CPT_VF_INT_VEC_E_DONE); 9548c2ecf20Sopenharmony_ci cptvf_free_irq_affinity(cptvf, CPT_VF_INT_VEC_E_MISC); 9558c2ecf20Sopenharmony_ci free_irq(pci_irq_vector(pdev, CPT_VF_INT_VEC_E_DONE), cptvf); 9568c2ecf20Sopenharmony_ci free_irq(pci_irq_vector(pdev, CPT_VF_INT_VEC_E_MISC), cptvf); 9578c2ecf20Sopenharmony_ci cptvf_sw_cleanup(cptvf); 9588c2ecf20Sopenharmony_ci pci_free_irq_vectors(cptvf->pdev); 9598c2ecf20Sopenharmony_ci pci_iounmap(pdev, cptvf->reg_base); 9608c2ecf20Sopenharmony_ci pci_release_regions(pdev); 9618c2ecf20Sopenharmony_ci pci_disable_device(pdev); 9628c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, NULL); 9638c2ecf20Sopenharmony_ci } 9648c2ecf20Sopenharmony_ci} 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci/* Supported devices */ 9678c2ecf20Sopenharmony_cistatic const struct pci_device_id otx_cptvf_id_table[] = { 9688c2ecf20Sopenharmony_ci {PCI_VDEVICE(CAVIUM, OTX_CPT_PCI_VF_DEVICE_ID), 0}, 9698c2ecf20Sopenharmony_ci { 0, } /* end of table */ 9708c2ecf20Sopenharmony_ci}; 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_cistatic struct pci_driver otx_cptvf_pci_driver = { 9738c2ecf20Sopenharmony_ci .name = DRV_NAME, 9748c2ecf20Sopenharmony_ci .id_table = otx_cptvf_id_table, 9758c2ecf20Sopenharmony_ci .probe = otx_cptvf_probe, 9768c2ecf20Sopenharmony_ci .remove = otx_cptvf_remove, 9778c2ecf20Sopenharmony_ci}; 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_cimodule_pci_driver(otx_cptvf_pci_driver); 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ciMODULE_AUTHOR("Marvell International Ltd."); 9828c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Marvell OcteonTX CPT Virtual Function Driver"); 9838c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 9848c2ecf20Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 9858c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, otx_cptvf_id_table); 986