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