1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright 2017 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 <rte_dev.h> 21 #include <ethdev_driver.h> 22 23 #include <fslmc_logs.h> 24 #include <rte_fslmc.h> 25 #include <mc/fsl_dpci.h> 26 #include "portal/dpaa2_hw_pvt.h" 27 #include "portal/dpaa2_hw_dpio.h" 28 29 TAILQ_HEAD(dpci_dev_list, dpaa2_dpci_dev); 30 static struct dpci_dev_list dpci_dev_list 31 = TAILQ_HEAD_INITIALIZER(dpci_dev_list); /*!< DPCI device list */ 32 33 static int 34 rte_dpaa2_create_dpci_device(int vdev_fd __rte_unused, 35 struct vfio_device_info *obj_info __rte_unused, 36 int dpci_id) 37 { 38 struct dpaa2_dpci_dev *dpci_node; 39 struct dpci_attr attr; 40 struct dpci_rx_queue_cfg rx_queue_cfg; 41 struct dpci_rx_queue_attr rx_attr; 42 struct dpci_tx_queue_attr tx_attr; 43 int ret, i; 44 45 /* Allocate DPAA2 dpci handle */ 46 dpci_node = rte_malloc(NULL, sizeof(struct dpaa2_dpci_dev), 0); 47 if (!dpci_node) { 48 DPAA2_BUS_ERR("Memory allocation failed for DPCI Device"); 49 return -ENOMEM; 50 } 51 52 /* Open the dpci object */ 53 dpci_node->dpci.regs = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX); 54 ret = dpci_open(&dpci_node->dpci, 55 CMD_PRI_LOW, dpci_id, &dpci_node->token); 56 if (ret) { 57 DPAA2_BUS_ERR("Resource alloc failure with err code: %d", ret); 58 goto err; 59 } 60 61 /* Get the device attributes */ 62 ret = dpci_get_attributes(&dpci_node->dpci, 63 CMD_PRI_LOW, dpci_node->token, &attr); 64 if (ret != 0) { 65 DPAA2_BUS_ERR("Reading device failed with err code: %d", ret); 66 goto err; 67 } 68 69 for (i = 0; i < DPAA2_DPCI_MAX_QUEUES; i++) { 70 struct dpaa2_queue *rxq; 71 72 memset(&rx_queue_cfg, 0, sizeof(struct dpci_rx_queue_cfg)); 73 ret = dpci_set_rx_queue(&dpci_node->dpci, 74 CMD_PRI_LOW, 75 dpci_node->token, 76 i, &rx_queue_cfg); 77 if (ret) { 78 DPAA2_BUS_ERR("Setting Rx queue failed with err code: %d", 79 ret); 80 goto err; 81 } 82 83 /* Allocate DQ storage for the DPCI Rx queues */ 84 rxq = &(dpci_node->rx_queue[i]); 85 rxq->q_storage = rte_malloc("dq_storage", 86 sizeof(struct queue_storage_info_t), 87 RTE_CACHE_LINE_SIZE); 88 if (!rxq->q_storage) { 89 DPAA2_BUS_ERR("q_storage allocation failed\n"); 90 ret = -ENOMEM; 91 goto err; 92 } 93 94 memset(rxq->q_storage, 0, sizeof(struct queue_storage_info_t)); 95 ret = dpaa2_alloc_dq_storage(rxq->q_storage); 96 if (ret) { 97 DPAA2_BUS_ERR("dpaa2_alloc_dq_storage failed\n"); 98 goto err; 99 } 100 } 101 102 /* Enable the device */ 103 ret = dpci_enable(&dpci_node->dpci, 104 CMD_PRI_LOW, dpci_node->token); 105 if (ret != 0) { 106 DPAA2_BUS_ERR("Enabling device failed with err code: %d", ret); 107 goto err; 108 } 109 110 for (i = 0; i < DPAA2_DPCI_MAX_QUEUES; i++) { 111 /* Get the Rx FQID's */ 112 ret = dpci_get_rx_queue(&dpci_node->dpci, 113 CMD_PRI_LOW, 114 dpci_node->token, i, 115 &rx_attr); 116 if (ret != 0) { 117 DPAA2_BUS_ERR("Rx queue fetch failed with err code: %d", 118 ret); 119 goto err; 120 } 121 dpci_node->rx_queue[i].fqid = rx_attr.fqid; 122 123 ret = dpci_get_tx_queue(&dpci_node->dpci, 124 CMD_PRI_LOW, 125 dpci_node->token, i, 126 &tx_attr); 127 if (ret != 0) { 128 DPAA2_BUS_ERR("Reading device failed with err code: %d", 129 ret); 130 goto err; 131 } 132 dpci_node->tx_queue[i].fqid = tx_attr.fqid; 133 } 134 135 dpci_node->dpci_id = dpci_id; 136 rte_atomic16_init(&dpci_node->in_use); 137 138 TAILQ_INSERT_TAIL(&dpci_dev_list, dpci_node, next); 139 140 return 0; 141 142 err: 143 for (i = 0; i < DPAA2_DPCI_MAX_QUEUES; i++) { 144 struct dpaa2_queue *rxq = &(dpci_node->rx_queue[i]); 145 146 if (rxq->q_storage) { 147 dpaa2_free_dq_storage(rxq->q_storage); 148 rte_free(rxq->q_storage); 149 } 150 } 151 rte_free(dpci_node); 152 153 return ret; 154 } 155 156 struct dpaa2_dpci_dev *rte_dpaa2_alloc_dpci_dev(void) 157 { 158 struct dpaa2_dpci_dev *dpci_dev = NULL; 159 160 /* Get DPCI dev handle from list using index */ 161 TAILQ_FOREACH(dpci_dev, &dpci_dev_list, next) { 162 if (dpci_dev && rte_atomic16_test_and_set(&dpci_dev->in_use)) 163 break; 164 } 165 166 return dpci_dev; 167 } 168 169 void rte_dpaa2_free_dpci_dev(struct dpaa2_dpci_dev *dpci) 170 { 171 struct dpaa2_dpci_dev *dpci_dev = NULL; 172 173 /* Match DPCI handle and mark it free */ 174 TAILQ_FOREACH(dpci_dev, &dpci_dev_list, next) { 175 if (dpci_dev == dpci) { 176 rte_atomic16_dec(&dpci_dev->in_use); 177 return; 178 } 179 } 180 } 181 182 static struct rte_dpaa2_object rte_dpaa2_dpci_obj = { 183 .dev_type = DPAA2_CI, 184 .create = rte_dpaa2_create_dpci_device, 185 }; 186 187 RTE_PMD_REGISTER_DPAA2_OBJECT(dpci, rte_dpaa2_dpci_obj); 188