1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2018 NXP 3 */ 4 5 #include <sys/queue.h> 6 #include <stdio.h> 7 #include <errno.h> 8 #include <stdint.h> 9 #include <string.h> 10 #include <unistd.h> 11 #include <stdarg.h> 12 13 #include <rte_ethdev.h> 14 #include <rte_log.h> 15 #include <rte_malloc.h> 16 #include <rte_flow_driver.h> 17 #include <rte_tailq.h> 18 19 #include <rte_fslmc.h> 20 #include <fsl_dpdmux.h> 21 #include <fsl_dpkg.h> 22 23 #include <dpaa2_ethdev.h> 24 #include <dpaa2_pmd_logs.h> 25 26 struct dpaa2_dpdmux_dev { 27 TAILQ_ENTRY(dpaa2_dpdmux_dev) next; 28 /**< Pointer to Next device instance */ 29 struct fsl_mc_io dpdmux; /** handle to DPDMUX portal object */ 30 uint16_t token; 31 uint32_t dpdmux_id; /*HW ID for DPDMUX object */ 32 uint8_t num_ifs; /* Number of interfaces in DPDMUX */ 33 }; 34 35 struct rte_flow { 36 struct dpdmux_rule_cfg rule; 37 }; 38 39 TAILQ_HEAD(dpdmux_dev_list, dpaa2_dpdmux_dev); 40 static struct dpdmux_dev_list dpdmux_dev_list = 41 TAILQ_HEAD_INITIALIZER(dpdmux_dev_list); /*!< DPDMUX device list */ 42 43 static struct dpaa2_dpdmux_dev *get_dpdmux_from_id(uint32_t dpdmux_id) 44 { 45 struct dpaa2_dpdmux_dev *dpdmux_dev = NULL; 46 47 /* Get DPBP dev handle from list using index */ 48 TAILQ_FOREACH(dpdmux_dev, &dpdmux_dev_list, next) { 49 if (dpdmux_dev->dpdmux_id == dpdmux_id) 50 break; 51 } 52 53 return dpdmux_dev; 54 } 55 56 struct rte_flow * 57 rte_pmd_dpaa2_mux_flow_create(uint32_t dpdmux_id, 58 struct rte_flow_item *pattern[], 59 struct rte_flow_action *actions[]) 60 { 61 struct dpaa2_dpdmux_dev *dpdmux_dev; 62 struct dpkg_profile_cfg kg_cfg; 63 const struct rte_flow_item_ipv4 *spec; 64 const struct rte_flow_action_vf *vf_conf; 65 struct dpdmux_cls_action dpdmux_action; 66 struct rte_flow *flow = NULL; 67 void *key_iova, *mask_iova, *key_cfg_iova = NULL; 68 int ret; 69 70 if (pattern[0]->type != RTE_FLOW_ITEM_TYPE_IPV4) { 71 DPAA2_PMD_ERR("Not supported pattern type: %d", 72 pattern[0]->type); 73 return NULL; 74 } 75 76 /* Find the DPDMUX from dpdmux_id in our list */ 77 dpdmux_dev = get_dpdmux_from_id(dpdmux_id); 78 if (!dpdmux_dev) { 79 DPAA2_PMD_ERR("Invalid dpdmux_id: %d", dpdmux_id); 80 return NULL; 81 } 82 83 key_cfg_iova = rte_zmalloc(NULL, DIST_PARAM_IOVA_SIZE, 84 RTE_CACHE_LINE_SIZE); 85 if (!key_cfg_iova) { 86 DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); 87 return NULL; 88 } 89 90 /* Currently taking only IP protocol as an extract type. 91 * This can be exended to other fields using pattern->type. 92 */ 93 memset(&kg_cfg, 0, sizeof(struct dpkg_profile_cfg)); 94 kg_cfg.extracts[0].extract.from_hdr.prot = NET_PROT_IP; 95 kg_cfg.extracts[0].extract.from_hdr.field = NH_FLD_IP_PROTO; 96 kg_cfg.extracts[0].type = DPKG_EXTRACT_FROM_HDR; 97 kg_cfg.extracts[0].extract.from_hdr.type = DPKG_FULL_FIELD; 98 kg_cfg.num_extracts = 1; 99 100 ret = dpkg_prepare_key_cfg(&kg_cfg, key_cfg_iova); 101 if (ret) { 102 DPAA2_PMD_ERR("dpkg_prepare_key_cfg failed: err(%d)", ret); 103 goto creation_error; 104 } 105 106 ret = dpdmux_set_custom_key(&dpdmux_dev->dpdmux, CMD_PRI_LOW, 107 dpdmux_dev->token, 108 (uint64_t)(DPAA2_VADDR_TO_IOVA(key_cfg_iova))); 109 if (ret) { 110 DPAA2_PMD_ERR("dpdmux_set_custom_key failed: err(%d)", ret); 111 goto creation_error; 112 } 113 114 /* As now our key extract parameters are set, let us configure 115 * the rule. 116 */ 117 flow = rte_zmalloc(NULL, sizeof(struct rte_flow) + 118 (2 * DIST_PARAM_IOVA_SIZE), RTE_CACHE_LINE_SIZE); 119 if (!flow) { 120 DPAA2_PMD_ERR( 121 "Memory allocation failure for rule configration\n"); 122 goto creation_error; 123 } 124 key_iova = (void *)((size_t)flow + sizeof(struct rte_flow)); 125 mask_iova = (void *)((size_t)key_iova + DIST_PARAM_IOVA_SIZE); 126 127 spec = (const struct rte_flow_item_ipv4 *)pattern[0]->spec; 128 memcpy(key_iova, (const void *)&spec->hdr.next_proto_id, 129 sizeof(uint8_t)); 130 memcpy(mask_iova, pattern[0]->mask, sizeof(uint8_t)); 131 132 flow->rule.key_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(key_iova)); 133 flow->rule.mask_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(mask_iova)); 134 flow->rule.key_size = sizeof(uint8_t); 135 136 vf_conf = (const struct rte_flow_action_vf *)(actions[0]->conf); 137 if (vf_conf->id == 0 || vf_conf->id > dpdmux_dev->num_ifs) { 138 DPAA2_PMD_ERR("Invalid destination id\n"); 139 goto creation_error; 140 } 141 dpdmux_action.dest_if = vf_conf->id; 142 143 ret = dpdmux_add_custom_cls_entry(&dpdmux_dev->dpdmux, CMD_PRI_LOW, 144 dpdmux_dev->token, &flow->rule, 145 &dpdmux_action); 146 if (ret) { 147 DPAA2_PMD_ERR("dpdmux_add_custom_cls_entry failed: err(%d)", 148 ret); 149 goto creation_error; 150 } 151 152 return flow; 153 154 creation_error: 155 rte_free((void *)key_cfg_iova); 156 rte_free((void *)flow); 157 return NULL; 158 } 159 160 static int 161 dpaa2_create_dpdmux_device(int vdev_fd __rte_unused, 162 struct vfio_device_info *obj_info __rte_unused, 163 int dpdmux_id) 164 { 165 struct dpaa2_dpdmux_dev *dpdmux_dev; 166 struct dpdmux_attr attr; 167 int ret; 168 169 PMD_INIT_FUNC_TRACE(); 170 171 /* Allocate DPAA2 dpdmux handle */ 172 dpdmux_dev = rte_malloc(NULL, sizeof(struct dpaa2_dpdmux_dev), 0); 173 if (!dpdmux_dev) { 174 DPAA2_PMD_ERR("Memory allocation failed for DPDMUX Device"); 175 return -1; 176 } 177 178 /* Open the dpdmux object */ 179 dpdmux_dev->dpdmux.regs = rte_mcp_ptr_list[MC_PORTAL_INDEX]; 180 ret = dpdmux_open(&dpdmux_dev->dpdmux, CMD_PRI_LOW, dpdmux_id, 181 &dpdmux_dev->token); 182 if (ret) { 183 DPAA2_PMD_ERR("Unable to open dpdmux object: err(%d)", ret); 184 goto init_err; 185 } 186 187 ret = dpdmux_get_attributes(&dpdmux_dev->dpdmux, CMD_PRI_LOW, 188 dpdmux_dev->token, &attr); 189 if (ret) { 190 DPAA2_PMD_ERR("Unable to get dpdmux attr: err(%d)", ret); 191 goto init_err; 192 } 193 194 ret = dpdmux_if_set_default(&dpdmux_dev->dpdmux, CMD_PRI_LOW, 195 dpdmux_dev->token, 1); 196 if (ret) { 197 DPAA2_PMD_ERR("setting default interface failed in %s", 198 __func__); 199 goto init_err; 200 } 201 202 dpdmux_dev->dpdmux_id = dpdmux_id; 203 dpdmux_dev->num_ifs = attr.num_ifs; 204 205 TAILQ_INSERT_TAIL(&dpdmux_dev_list, dpdmux_dev, next); 206 207 return 0; 208 209 init_err: 210 if (dpdmux_dev) 211 rte_free(dpdmux_dev); 212 213 return -1; 214 } 215 216 static struct rte_dpaa2_object rte_dpaa2_dpdmux_obj = { 217 .dev_type = DPAA2_MUX, 218 .create = dpaa2_create_dpdmux_device, 219 }; 220 221 RTE_PMD_REGISTER_DPAA2_OBJECT(dpdmux, rte_dpaa2_dpdmux_obj); 222