1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright 2017, 2020, 2023 NXP 4 * 5 */ 6 7 #include <unistd.h> 8 #include <stdio.h> 9 #include <sys/types.h> 10 #include <string.h> 11 #include <stdlib.h> 12 #include <fcntl.h> 13 #include <errno.h> 14 15 #include <rte_malloc.h> 16 #include <rte_memcpy.h> 17 #include <rte_string_fns.h> 18 #include <rte_cycles.h> 19 #include <rte_kvargs.h> 20 #include <dev_driver.h> 21 #include <ethdev_driver.h> 22 23 #include <bus_fslmc_driver.h> 24 #include <mc/fsl_dpcon.h> 25 #include <portal/dpaa2_hw_pvt.h> 26 #include "dpaa2_eventdev.h" 27 #include "dpaa2_eventdev_logs.h" 28 29 TAILQ_HEAD(dpcon_dev_list, dpaa2_dpcon_dev); 30 static struct dpcon_dev_list dpcon_dev_list 31 = TAILQ_HEAD_INITIALIZER(dpcon_dev_list); /*!< DPCON device list */ 32 33 static struct dpaa2_dpcon_dev *get_dpcon_from_id(uint32_t dpcon_id) 34 { 35 struct dpaa2_dpcon_dev *dpcon_dev = NULL; 36 37 /* Get DPCONC dev handle from list using index */ 38 TAILQ_FOREACH(dpcon_dev, &dpcon_dev_list, next) { 39 if (dpcon_dev->dpcon_id == dpcon_id) 40 break; 41 } 42 43 return dpcon_dev; 44 } 45 46 static int 47 rte_dpaa2_create_dpcon_device(int dev_fd __rte_unused, 48 struct vfio_device_info *obj_info __rte_unused, 49 struct rte_dpaa2_device *obj) 50 { 51 struct dpaa2_dpcon_dev *dpcon_node; 52 struct dpcon_attr attr; 53 int ret, dpcon_id = obj->object_id; 54 55 /* Allocate DPAA2 dpcon handle */ 56 dpcon_node = rte_malloc(NULL, sizeof(struct dpaa2_dpcon_dev), 0); 57 if (!dpcon_node) { 58 DPAA2_EVENTDEV_ERR( 59 "Memory allocation failed for dpcon device"); 60 return -1; 61 } 62 63 /* Open the dpcon object */ 64 dpcon_node->dpcon.regs = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX); 65 ret = dpcon_open(&dpcon_node->dpcon, 66 CMD_PRI_LOW, dpcon_id, &dpcon_node->token); 67 if (ret) { 68 DPAA2_EVENTDEV_ERR("Unable to open dpcon device: err(%d)", 69 ret); 70 rte_free(dpcon_node); 71 return -1; 72 } 73 74 /* Get the device attributes */ 75 ret = dpcon_get_attributes(&dpcon_node->dpcon, 76 CMD_PRI_LOW, dpcon_node->token, &attr); 77 if (ret != 0) { 78 DPAA2_EVENTDEV_ERR("dpcon attribute fetch failed: err(%d)", 79 ret); 80 rte_free(dpcon_node); 81 return -1; 82 } 83 84 /* Updating device specific private information*/ 85 dpcon_node->qbman_ch_id = attr.qbman_ch_id; 86 dpcon_node->num_priorities = attr.num_priorities; 87 dpcon_node->dpcon_id = dpcon_id; 88 rte_atomic16_init(&dpcon_node->in_use); 89 90 TAILQ_INSERT_TAIL(&dpcon_dev_list, dpcon_node, next); 91 92 return 0; 93 } 94 95 struct dpaa2_dpcon_dev *rte_dpaa2_alloc_dpcon_dev(void) 96 { 97 struct dpaa2_dpcon_dev *dpcon_dev = NULL; 98 99 /* Get DPCON dev handle from list using index */ 100 TAILQ_FOREACH(dpcon_dev, &dpcon_dev_list, next) { 101 if (dpcon_dev && rte_atomic16_test_and_set(&dpcon_dev->in_use)) 102 break; 103 } 104 105 return dpcon_dev; 106 } 107 108 void rte_dpaa2_free_dpcon_dev(struct dpaa2_dpcon_dev *dpcon) 109 { 110 struct dpaa2_dpcon_dev *dpcon_dev = NULL; 111 112 /* Match DPCON handle and mark it free */ 113 TAILQ_FOREACH(dpcon_dev, &dpcon_dev_list, next) { 114 if (dpcon_dev == dpcon) { 115 rte_atomic16_dec(&dpcon_dev->in_use); 116 return; 117 } 118 } 119 } 120 121 122 static void 123 rte_dpaa2_close_dpcon_device(int object_id) 124 { 125 struct dpaa2_dpcon_dev *dpcon_dev = NULL; 126 127 dpcon_dev = get_dpcon_from_id((uint32_t)object_id); 128 129 if (dpcon_dev) { 130 rte_dpaa2_free_dpcon_dev(dpcon_dev); 131 dpcon_close(&dpcon_dev->dpcon, CMD_PRI_LOW, dpcon_dev->token); 132 TAILQ_REMOVE(&dpcon_dev_list, dpcon_dev, next); 133 rte_free(dpcon_dev); 134 } 135 } 136 137 static struct rte_dpaa2_object rte_dpaa2_dpcon_obj = { 138 .dev_type = DPAA2_CON, 139 .create = rte_dpaa2_create_dpcon_device, 140 .close = rte_dpaa2_close_dpcon_device, 141 }; 142 143 RTE_PMD_REGISTER_DPAA2_OBJECT(dpcon, rte_dpaa2_dpcon_obj); 144