dpdk/drivers/net/dpaa/dpaa_flow.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright 2017-2019,2021 NXP
   3 */
   4
   5/* System headers */
   6#include <stdio.h>
   7#include <inttypes.h>
   8#include <unistd.h>
   9#include <sys/types.h>
  10
  11#include <dpaa_ethdev.h>
  12#include <dpaa_flow.h>
  13#include <rte_dpaa_logs.h>
  14#include <fmlib/fm_port_ext.h>
  15#include <fmlib/fm_vsp_ext.h>
  16
  17#define DPAA_MAX_NUM_ETH_DEV    8
  18
  19static inline
  20ioc_fm_pcd_extract_entry_t *
  21SCH_EXT_ARR(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
  22{
  23return &scheme_params->param.key_ext_and_hash.extract_array[hdr_idx];
  24}
  25
  26#define SCH_EXT_HDR(scheme_params, hdr_idx) \
  27        SCH_EXT_ARR(scheme_params, hdr_idx)->extract_params.extract_by_hdr
  28
  29#define SCH_EXT_FULL_FLD(scheme_params, hdr_idx) \
  30        SCH_EXT_HDR(scheme_params, hdr_idx).extract_by_hdr_type.full_field
  31
  32/* FM global info */
  33struct dpaa_fm_info {
  34        t_handle fman_handle;
  35        t_handle pcd_handle;
  36};
  37
  38/*FM model to read and write from file */
  39struct dpaa_fm_model {
  40        uint32_t dev_count;
  41        uint8_t device_order[DPAA_MAX_NUM_ETH_DEV];
  42        t_fm_port_params fm_port_params[DPAA_MAX_NUM_ETH_DEV];
  43        t_handle netenv_devid[DPAA_MAX_NUM_ETH_DEV];
  44        t_handle scheme_devid[DPAA_MAX_NUM_ETH_DEV][2];
  45};
  46
  47static struct dpaa_fm_info fm_info;
  48static struct dpaa_fm_model fm_model;
  49static const char *fm_log = "/tmp/fmdpdk.bin";
  50
  51static inline uint8_t fm_default_vsp_id(struct fman_if *fif)
  52{
  53        /* Avoid being same as base profile which could be used
  54         * for kernel interface of shared mac.
  55         */
  56        if (fif->base_profile_id)
  57                return 0;
  58        else
  59                return DPAA_DEFAULT_RXQ_VSP_ID;
  60}
  61
  62static void fm_prev_cleanup(void)
  63{
  64        uint32_t fman_id = 0, i = 0, devid;
  65        struct dpaa_if dpaa_intf = {0};
  66        t_fm_pcd_params fm_pcd_params = {0};
  67        PMD_INIT_FUNC_TRACE();
  68
  69        fm_info.fman_handle = fm_open(fman_id);
  70        if (!fm_info.fman_handle) {
  71                printf("\n%s- unable to open FMAN", __func__);
  72                return;
  73        }
  74
  75        fm_pcd_params.h_fm = fm_info.fman_handle;
  76        fm_pcd_params.prs_support = true;
  77        fm_pcd_params.kg_support = true;
  78        /* FM PCD Open */
  79        fm_info.pcd_handle = fm_pcd_open(&fm_pcd_params);
  80        if (!fm_info.pcd_handle) {
  81                printf("\n%s- unable to open PCD", __func__);
  82                return;
  83        }
  84
  85        while (i < fm_model.dev_count) {
  86                devid = fm_model.device_order[i];
  87                /* FM Port Open */
  88                fm_model.fm_port_params[devid].h_fm = fm_info.fman_handle;
  89                dpaa_intf.port_handle =
  90                                fm_port_open(&fm_model.fm_port_params[devid]);
  91                dpaa_intf.scheme_handle[0] = create_device(fm_info.pcd_handle,
  92                                        fm_model.scheme_devid[devid][0]);
  93                dpaa_intf.scheme_count = 1;
  94                if (fm_model.scheme_devid[devid][1]) {
  95                        dpaa_intf.scheme_handle[1] =
  96                                create_device(fm_info.pcd_handle,
  97                                        fm_model.scheme_devid[devid][1]);
  98                        if (dpaa_intf.scheme_handle[1])
  99                                dpaa_intf.scheme_count++;
 100                }
 101
 102                dpaa_intf.netenv_handle = create_device(fm_info.pcd_handle,
 103                                        fm_model.netenv_devid[devid]);
 104                i++;
 105                if (!dpaa_intf.netenv_handle ||
 106                        !dpaa_intf.scheme_handle[0] ||
 107                        !dpaa_intf.port_handle)
 108                        continue;
 109
 110                if (dpaa_fm_deconfig(&dpaa_intf, NULL))
 111                        printf("\nDPAA FM deconfig failed\n");
 112        }
 113
 114        if (dpaa_fm_term())
 115                printf("\nDPAA FM term failed\n");
 116
 117        memset(&fm_model, 0, sizeof(struct dpaa_fm_model));
 118}
 119
 120void dpaa_write_fm_config_to_file(void)
 121{
 122        size_t bytes_write;
 123        FILE *fp = fopen(fm_log, "wb");
 124        PMD_INIT_FUNC_TRACE();
 125
 126        if (!fp) {
 127                DPAA_PMD_ERR("File open failed");
 128                return;
 129        }
 130        bytes_write = fwrite(&fm_model, sizeof(struct dpaa_fm_model), 1, fp);
 131        if (!bytes_write) {
 132                DPAA_PMD_WARN("No bytes write");
 133                fclose(fp);
 134                return;
 135        }
 136        fclose(fp);
 137}
 138
 139static void dpaa_read_fm_config_from_file(void)
 140{
 141        size_t bytes_read;
 142        FILE *fp = fopen(fm_log, "rb");
 143        PMD_INIT_FUNC_TRACE();
 144
 145        if (!fp)
 146                return;
 147        DPAA_PMD_INFO("Previous DPDK-FM config instance present, cleaning up.");
 148
 149        bytes_read = fread(&fm_model, sizeof(struct dpaa_fm_model), 1, fp);
 150        if (!bytes_read) {
 151                DPAA_PMD_WARN("No bytes read");
 152                fclose(fp);
 153                return;
 154        }
 155        fclose(fp);
 156
 157        /*FM cleanup from previous configured app */
 158        fm_prev_cleanup();
 159}
 160
 161static inline int
 162set_hash_params_eth(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
 163{
 164        int k;
 165
 166        for (k = 0; k < 2; k++) {
 167                SCH_EXT_ARR(scheme_params, hdr_idx)->type =
 168                                                e_IOC_FM_PCD_EXTRACT_BY_HDR;
 169                SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
 170                                                HEADER_TYPE_ETH;
 171                SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
 172                                                e_IOC_FM_PCD_HDR_INDEX_NONE;
 173                SCH_EXT_HDR(scheme_params, hdr_idx).type =
 174                                                e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
 175                if (k == 0)
 176                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).eth =
 177                                                IOC_NET_HF_ETH_SA;
 178                else
 179                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).eth =
 180                                                IOC_NET_HF_ETH_DA;
 181                hdr_idx++;
 182        }
 183        return hdr_idx;
 184}
 185
 186static inline int
 187set_hash_params_ipv4(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
 188{
 189        int k;
 190
 191        for (k = 0; k < 2; k++) {
 192                SCH_EXT_ARR(scheme_params, hdr_idx)->type =
 193                                                e_IOC_FM_PCD_EXTRACT_BY_HDR;
 194                SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
 195                                                HEADER_TYPE_IPV4;
 196                SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
 197                                                e_IOC_FM_PCD_HDR_INDEX_NONE;
 198                SCH_EXT_HDR(scheme_params, hdr_idx).type =
 199                                                e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
 200                if (k == 0)
 201                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv4 =
 202                                        ioc_net_hf_ipv_4_src_ip;
 203                else
 204                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv4 =
 205                                        ioc_net_hf_ipv_4_dst_ip;
 206                hdr_idx++;
 207        }
 208        return hdr_idx;
 209}
 210
 211static inline int
 212set_hash_params_ipv6(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
 213{
 214        int k;
 215
 216        for (k = 0; k < 2; k++) {
 217                SCH_EXT_ARR(scheme_params, hdr_idx)->type =
 218                                                e_IOC_FM_PCD_EXTRACT_BY_HDR;
 219                SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
 220                                                        HEADER_TYPE_IPV6;
 221                SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
 222                                                e_IOC_FM_PCD_HDR_INDEX_NONE;
 223                SCH_EXT_HDR(scheme_params, hdr_idx).type =
 224                                                e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
 225                if (k == 0)
 226                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv6 =
 227                                        ioc_net_hf_ipv_6_src_ip;
 228                else
 229                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv6 =
 230                                        ioc_net_hf_ipv_6_dst_ip;
 231                hdr_idx++;
 232        }
 233        return hdr_idx;
 234}
 235
 236static inline int
 237set_hash_params_udp(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
 238{
 239        int k;
 240
 241        for (k = 0; k < 2; k++) {
 242                SCH_EXT_ARR(scheme_params, hdr_idx)->type =
 243                                                e_IOC_FM_PCD_EXTRACT_BY_HDR;
 244                SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
 245                                                HEADER_TYPE_UDP;
 246                SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
 247                                                e_IOC_FM_PCD_HDR_INDEX_NONE;
 248                SCH_EXT_HDR(scheme_params, hdr_idx).type =
 249                                                e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
 250                if (k == 0)
 251                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).udp =
 252                                        IOC_NET_HF_UDP_PORT_SRC;
 253                else
 254                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).udp =
 255                                        IOC_NET_HF_UDP_PORT_DST;
 256                hdr_idx++;
 257        }
 258        return hdr_idx;
 259}
 260
 261static inline int
 262set_hash_params_tcp(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
 263{
 264        int k;
 265
 266        for (k = 0; k < 2; k++) {
 267                SCH_EXT_ARR(scheme_params, hdr_idx)->type =
 268                                                e_IOC_FM_PCD_EXTRACT_BY_HDR;
 269                SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
 270                                                HEADER_TYPE_TCP;
 271                SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
 272                                                e_IOC_FM_PCD_HDR_INDEX_NONE;
 273                SCH_EXT_HDR(scheme_params, hdr_idx).type =
 274                                                e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
 275                if (k == 0)
 276                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).tcp =
 277                                        IOC_NET_HF_TCP_PORT_SRC;
 278                else
 279                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).tcp =
 280                                        IOC_NET_HF_TCP_PORT_DST;
 281                hdr_idx++;
 282        }
 283        return hdr_idx;
 284}
 285
 286static inline int
 287set_hash_params_sctp(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
 288{
 289        int k;
 290
 291        for (k = 0; k < 2; k++) {
 292                SCH_EXT_ARR(scheme_params, hdr_idx)->type =
 293                                                e_IOC_FM_PCD_EXTRACT_BY_HDR;
 294                SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
 295                                                HEADER_TYPE_SCTP;
 296                SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
 297                                                e_IOC_FM_PCD_HDR_INDEX_NONE;
 298                SCH_EXT_HDR(scheme_params, hdr_idx).type =
 299                                                e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
 300                if (k == 0)
 301                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).sctp =
 302                                        IOC_NET_HF_SCTP_PORT_SRC;
 303                else
 304                        SCH_EXT_FULL_FLD(scheme_params, hdr_idx).sctp =
 305                                        IOC_NET_HF_SCTP_PORT_DST;
 306                hdr_idx++;
 307        }
 308        return hdr_idx;
 309}
 310
 311/* Set scheme params for hash distribution */
 312static int set_scheme_params(ioc_fm_pcd_kg_scheme_params_t *scheme_params,
 313        ioc_fm_pcd_net_env_params_t *dist_units,
 314        struct dpaa_if *dpaa_intf,
 315        struct fman_if *fif)
 316{
 317        int dist_idx, hdr_idx = 0;
 318        PMD_INIT_FUNC_TRACE();
 319
 320        if (fif->num_profiles) {
 321                scheme_params->param.override_storage_profile = true;
 322                scheme_params->param.storage_profile.direct = true;
 323                scheme_params->param.storage_profile.profile_select
 324                        .direct_relative_profile_id = fm_default_vsp_id(fif);
 325        }
 326
 327        scheme_params->param.use_hash = 1;
 328        scheme_params->param.modify = false;
 329        scheme_params->param.always_direct = false;
 330        scheme_params->param.scheme_counter.update = 1;
 331        scheme_params->param.scheme_counter.value = 0;
 332        scheme_params->param.next_engine = e_IOC_FM_PCD_DONE;
 333        scheme_params->param.base_fqid = dpaa_intf->rx_queues[0].fqid;
 334        scheme_params->param.net_env_params.net_env_id =
 335                dpaa_intf->netenv_handle;
 336        scheme_params->param.net_env_params.num_of_distinction_units =
 337                dist_units->param.num_of_distinction_units;
 338
 339        scheme_params->param.key_ext_and_hash.hash_dist_num_of_fqids =
 340                        dpaa_intf->nb_rx_queues;
 341        scheme_params->param.key_ext_and_hash.num_of_used_extracts =
 342                        2 * dist_units->param.num_of_distinction_units;
 343
 344        for (dist_idx = 0; dist_idx <
 345                dist_units->param.num_of_distinction_units;
 346                dist_idx++) {
 347                switch (dist_units->param.units[dist_idx].hdrs[0].hdr) {
 348                case HEADER_TYPE_ETH:
 349                        hdr_idx = set_hash_params_eth(scheme_params, hdr_idx);
 350                        break;
 351
 352                case HEADER_TYPE_IPV4:
 353                        hdr_idx = set_hash_params_ipv4(scheme_params, hdr_idx);
 354                        break;
 355
 356                case HEADER_TYPE_IPV6:
 357                        hdr_idx = set_hash_params_ipv6(scheme_params, hdr_idx);
 358                        break;
 359
 360                case HEADER_TYPE_UDP:
 361                        hdr_idx = set_hash_params_udp(scheme_params, hdr_idx);
 362                        break;
 363
 364                case HEADER_TYPE_TCP:
 365                        hdr_idx = set_hash_params_tcp(scheme_params, hdr_idx);
 366                        break;
 367
 368                case HEADER_TYPE_SCTP:
 369                        hdr_idx = set_hash_params_sctp(scheme_params, hdr_idx);
 370                        break;
 371
 372                default:
 373                        DPAA_PMD_ERR("Invalid Distinction Unit");
 374                        return -1;
 375                }
 376        }
 377
 378        return 0;
 379}
 380
 381static void set_dist_units(ioc_fm_pcd_net_env_params_t *dist_units,
 382                           uint64_t req_dist_set)
 383{
 384        uint32_t loop = 0, dist_idx = 0, dist_field = 0;
 385        int l2_configured = 0, ipv4_configured = 0, ipv6_configured = 0;
 386        int udp_configured = 0, tcp_configured = 0, sctp_configured = 0;
 387        PMD_INIT_FUNC_TRACE();
 388
 389        if (!req_dist_set)
 390                dist_units->param.units[dist_idx++].hdrs[0].hdr =
 391                        HEADER_TYPE_ETH;
 392
 393        while (req_dist_set) {
 394                if (req_dist_set % 2 != 0) {
 395                        dist_field = 1U << loop;
 396                        switch (dist_field) {
 397                        case ETH_RSS_L2_PAYLOAD:
 398
 399                                if (l2_configured)
 400                                        break;
 401                                l2_configured = 1;
 402
 403                                dist_units->param.units[dist_idx++].hdrs[0].hdr
 404                                        = HEADER_TYPE_ETH;
 405                                break;
 406
 407                        case ETH_RSS_IPV4:
 408                        case ETH_RSS_FRAG_IPV4:
 409                        case ETH_RSS_NONFRAG_IPV4_OTHER:
 410
 411                                if (ipv4_configured)
 412                                        break;
 413                                ipv4_configured = 1;
 414                                dist_units->param.units[dist_idx++].hdrs[0].hdr
 415                                        = HEADER_TYPE_IPV4;
 416                                break;
 417
 418                        case ETH_RSS_IPV6:
 419                        case ETH_RSS_FRAG_IPV6:
 420                        case ETH_RSS_NONFRAG_IPV6_OTHER:
 421                        case ETH_RSS_IPV6_EX:
 422
 423                                if (ipv6_configured)
 424                                        break;
 425                                ipv6_configured = 1;
 426                                dist_units->param.units[dist_idx++].hdrs[0].hdr
 427                                        = HEADER_TYPE_IPV6;
 428                                break;
 429
 430                        case ETH_RSS_NONFRAG_IPV4_TCP:
 431                        case ETH_RSS_NONFRAG_IPV6_TCP:
 432                        case ETH_RSS_IPV6_TCP_EX:
 433
 434                                if (tcp_configured)
 435                                        break;
 436                                tcp_configured = 1;
 437                                dist_units->param.units[dist_idx++].hdrs[0].hdr
 438                                        = HEADER_TYPE_TCP;
 439                                break;
 440
 441                        case ETH_RSS_NONFRAG_IPV4_UDP:
 442                        case ETH_RSS_NONFRAG_IPV6_UDP:
 443                        case ETH_RSS_IPV6_UDP_EX:
 444
 445                                if (udp_configured)
 446                                        break;
 447                                udp_configured = 1;
 448                                dist_units->param.units[dist_idx++].hdrs[0].hdr
 449                                        = HEADER_TYPE_UDP;
 450                                break;
 451
 452                        case ETH_RSS_NONFRAG_IPV4_SCTP:
 453                        case ETH_RSS_NONFRAG_IPV6_SCTP:
 454
 455                                if (sctp_configured)
 456                                        break;
 457                                sctp_configured = 1;
 458
 459                                dist_units->param.units[dist_idx++].hdrs[0].hdr
 460                                        = HEADER_TYPE_SCTP;
 461                                break;
 462
 463                        default:
 464                                DPAA_PMD_ERR("Bad flow distribution option");
 465                        }
 466                }
 467                req_dist_set = req_dist_set >> 1;
 468                loop++;
 469        }
 470
 471        /* Dist units is set to dist_idx */
 472        dist_units->param.num_of_distinction_units = dist_idx;
 473}
 474
 475/* Apply PCD configuration on interface */
 476static inline int set_port_pcd(struct dpaa_if *dpaa_intf)
 477{
 478        int ret = 0;
 479        unsigned int idx;
 480        ioc_fm_port_pcd_params_t pcd_param;
 481        ioc_fm_port_pcd_prs_params_t prs_param;
 482        ioc_fm_port_pcd_kg_params_t  kg_param;
 483
 484        PMD_INIT_FUNC_TRACE();
 485
 486        /* PCD support for hash distribution */
 487        uint8_t pcd_support = e_FM_PORT_PCD_SUPPORT_PRS_AND_KG;
 488
 489        memset(&pcd_param, 0, sizeof(pcd_param));
 490        memset(&prs_param, 0, sizeof(prs_param));
 491        memset(&kg_param, 0, sizeof(kg_param));
 492
 493        /* Set parse params */
 494        prs_param.first_prs_hdr = HEADER_TYPE_ETH;
 495
 496        /* Set kg params */
 497        for (idx = 0; idx < dpaa_intf->scheme_count; idx++)
 498                kg_param.scheme_ids[idx] = dpaa_intf->scheme_handle[idx];
 499        kg_param.num_schemes = dpaa_intf->scheme_count;
 500
 501        /* Set pcd params */
 502        pcd_param.net_env_id = dpaa_intf->netenv_handle;
 503        pcd_param.pcd_support = pcd_support;
 504        pcd_param.p_kg_params = &kg_param;
 505        pcd_param.p_prs_params = &prs_param;
 506
 507        /* FM PORT Disable */
 508        ret = fm_port_disable(dpaa_intf->port_handle);
 509        if (ret != E_OK) {
 510                DPAA_PMD_ERR("fm_port_disable: Failed");
 511                return ret;
 512        }
 513
 514        /* FM PORT SetPCD */
 515        ret = fm_port_set_pcd(dpaa_intf->port_handle, &pcd_param);
 516        if (ret != E_OK) {
 517                DPAA_PMD_ERR("fm_port_set_pcd: Failed");
 518                return ret;
 519        }
 520
 521        /* FM PORT Enable */
 522        ret = fm_port_enable(dpaa_intf->port_handle);
 523        if (ret != E_OK) {
 524                DPAA_PMD_ERR("fm_port_enable: Failed");
 525                goto fm_port_delete_pcd;
 526        }
 527
 528        return 0;
 529
 530fm_port_delete_pcd:
 531        /* FM PORT DeletePCD */
 532        ret = fm_port_delete_pcd(dpaa_intf->port_handle);
 533        if (ret != E_OK) {
 534                DPAA_PMD_ERR("fm_port_delete_pcd: Failed\n");
 535                return ret;
 536        }
 537        return -1;
 538}
 539
 540/* Unset PCD NerEnv and scheme */
 541static inline void unset_pcd_netenv_scheme(struct dpaa_if *dpaa_intf)
 542{
 543        int ret;
 544        PMD_INIT_FUNC_TRACE();
 545
 546        /* reduce scheme count */
 547        if (dpaa_intf->scheme_count)
 548                dpaa_intf->scheme_count--;
 549
 550        DPAA_PMD_DEBUG("KG SCHEME DEL %d handle =%p",
 551                dpaa_intf->scheme_count,
 552                dpaa_intf->scheme_handle[dpaa_intf->scheme_count]);
 553
 554        ret = fm_pcd_kg_scheme_delete(dpaa_intf->scheme_handle
 555                                        [dpaa_intf->scheme_count]);
 556        if (ret != E_OK)
 557                DPAA_PMD_ERR("fm_pcd_kg_scheme_delete: Failed");
 558
 559        dpaa_intf->scheme_handle[dpaa_intf->scheme_count] = NULL;
 560}
 561
 562/* Set PCD NetEnv and Scheme and default scheme */
 563static inline int set_default_scheme(struct dpaa_if *dpaa_intf)
 564{
 565        ioc_fm_pcd_kg_scheme_params_t scheme_params;
 566        int idx = dpaa_intf->scheme_count;
 567        PMD_INIT_FUNC_TRACE();
 568
 569        /* Set PCD NetEnvCharacteristics */
 570        memset(&scheme_params, 0, sizeof(scheme_params));
 571
 572        /* Adding 10 to default schemes as the number of interface would be
 573         * lesser than 10 and the relative scheme ids should be unique for
 574         * every scheme.
 575         */
 576        scheme_params.param.scm_id.relative_scheme_id =
 577                10 + dpaa_intf->ifid;
 578        scheme_params.param.use_hash = 0;
 579        scheme_params.param.next_engine = e_IOC_FM_PCD_DONE;
 580        scheme_params.param.net_env_params.num_of_distinction_units = 0;
 581        scheme_params.param.net_env_params.net_env_id =
 582                dpaa_intf->netenv_handle;
 583        scheme_params.param.base_fqid = dpaa_intf->rx_queues[0].fqid;
 584        scheme_params.param.key_ext_and_hash.hash_dist_num_of_fqids = 1;
 585        scheme_params.param.key_ext_and_hash.num_of_used_extracts = 0;
 586        scheme_params.param.modify = false;
 587        scheme_params.param.always_direct = false;
 588        scheme_params.param.scheme_counter.update = 1;
 589        scheme_params.param.scheme_counter.value = 0;
 590
 591        /* FM PCD KgSchemeSet */
 592        dpaa_intf->scheme_handle[idx] =
 593                fm_pcd_kg_scheme_set(fm_info.pcd_handle, &scheme_params);
 594        DPAA_PMD_DEBUG("KG SCHEME SET %d handle =%p",
 595                idx, dpaa_intf->scheme_handle[idx]);
 596        if (!dpaa_intf->scheme_handle[idx]) {
 597                DPAA_PMD_ERR("fm_pcd_kg_scheme_set: Failed");
 598                return -1;
 599        }
 600
 601        fm_model.scheme_devid[dpaa_intf->ifid][idx] =
 602                                get_device_id(dpaa_intf->scheme_handle[idx]);
 603        dpaa_intf->scheme_count++;
 604        return 0;
 605}
 606
 607
 608/* Set PCD NetEnv and Scheme and default scheme */
 609static inline int set_pcd_netenv_scheme(struct dpaa_if *dpaa_intf,
 610                                        uint64_t req_dist_set,
 611                                        struct fman_if *fif)
 612{
 613        int ret = -1;
 614        ioc_fm_pcd_net_env_params_t dist_units;
 615        ioc_fm_pcd_kg_scheme_params_t scheme_params;
 616        int idx = dpaa_intf->scheme_count;
 617        PMD_INIT_FUNC_TRACE();
 618
 619        /* Set PCD NetEnvCharacteristics */
 620        memset(&dist_units, 0, sizeof(dist_units));
 621        memset(&scheme_params, 0, sizeof(scheme_params));
 622
 623        /* Set dist unit header type */
 624        set_dist_units(&dist_units, req_dist_set);
 625
 626        scheme_params.param.scm_id.relative_scheme_id = dpaa_intf->ifid;
 627
 628        /* Set PCD Scheme params */
 629        ret = set_scheme_params(&scheme_params, &dist_units, dpaa_intf, fif);
 630        if (ret) {
 631                DPAA_PMD_ERR("Set scheme params: Failed");
 632                return -1;
 633        }
 634
 635        /* FM PCD KgSchemeSet */
 636        dpaa_intf->scheme_handle[idx] =
 637                fm_pcd_kg_scheme_set(fm_info.pcd_handle, &scheme_params);
 638        DPAA_PMD_DEBUG("KG SCHEME SET %d handle =%p",
 639                        idx, dpaa_intf->scheme_handle[idx]);
 640        if (!dpaa_intf->scheme_handle[idx]) {
 641                DPAA_PMD_ERR("fm_pcd_kg_scheme_set: Failed");
 642                return -1;
 643        }
 644
 645        fm_model.scheme_devid[dpaa_intf->ifid][idx] =
 646                                get_device_id(dpaa_intf->scheme_handle[idx]);
 647        dpaa_intf->scheme_count++;
 648        return 0;
 649}
 650
 651
 652static inline int get_port_type(struct fman_if *fif)
 653{
 654        if (fif->mac_type == fman_mac_1g)
 655                return e_FM_PORT_TYPE_RX;
 656        else if (fif->mac_type == fman_mac_2_5g)
 657                return e_FM_PORT_TYPE_RX_2_5G;
 658        else if (fif->mac_type == fman_mac_10g)
 659                return e_FM_PORT_TYPE_RX_10G;
 660
 661        DPAA_PMD_ERR("MAC type unsupported");
 662        return -1;
 663}
 664
 665static inline int set_fm_port_handle(struct dpaa_if *dpaa_intf,
 666                                     uint64_t req_dist_set,
 667                                     struct fman_if *fif)
 668{
 669        t_fm_port_params        fm_port_params;
 670        ioc_fm_pcd_net_env_params_t dist_units;
 671        PMD_INIT_FUNC_TRACE();
 672
 673        /* FMAN mac indexes mappings (0 is unused,
 674         * first 8 are for 1G, next for 10G ports
 675         */
 676        uint8_t mac_idx[] = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1};
 677
 678        /* Memset FM port params */
 679        memset(&fm_port_params, 0, sizeof(fm_port_params));
 680
 681        /* Set FM port params */
 682        fm_port_params.h_fm = fm_info.fman_handle;
 683        fm_port_params.port_type = get_port_type(fif);
 684        fm_port_params.port_id = mac_idx[fif->mac_idx];
 685
 686        /* FM PORT Open */
 687        dpaa_intf->port_handle = fm_port_open(&fm_port_params);
 688        if (!dpaa_intf->port_handle) {
 689                DPAA_PMD_ERR("fm_port_open: Failed\n");
 690                return -1;
 691        }
 692
 693        fm_model.fm_port_params[dpaa_intf->ifid] = fm_port_params;
 694
 695        /* Set PCD NetEnvCharacteristics */
 696        memset(&dist_units, 0, sizeof(dist_units));
 697
 698        /* Set dist unit header type */
 699        set_dist_units(&dist_units, req_dist_set);
 700
 701        /* FM PCD NetEnvCharacteristicsSet */
 702        dpaa_intf->netenv_handle =
 703                fm_pcd_net_env_characteristics_set(fm_info.pcd_handle,
 704                                                        &dist_units);
 705        if (!dpaa_intf->netenv_handle) {
 706                DPAA_PMD_ERR("fm_pcd_net_env_characteristics_set: Failed");
 707                return -1;
 708        }
 709
 710        fm_model.netenv_devid[dpaa_intf->ifid] =
 711                                get_device_id(dpaa_intf->netenv_handle);
 712
 713        return 0;
 714}
 715
 716/* De-Configure DPAA FM */
 717int dpaa_fm_deconfig(struct dpaa_if *dpaa_intf,
 718                        struct fman_if *fif __rte_unused)
 719{
 720        int ret;
 721        unsigned int idx;
 722
 723        PMD_INIT_FUNC_TRACE();
 724
 725        /* FM PORT Disable */
 726        ret = fm_port_disable(dpaa_intf->port_handle);
 727        if (ret != E_OK) {
 728                DPAA_PMD_ERR("fm_port_disable: Failed");
 729                return ret;
 730        }
 731
 732        /* FM PORT DeletePCD */
 733        ret = fm_port_delete_pcd(dpaa_intf->port_handle);
 734        if (ret != E_OK) {
 735                DPAA_PMD_ERR("fm_port_delete_pcd: Failed");
 736                return ret;
 737        }
 738
 739        for (idx = 0; idx < dpaa_intf->scheme_count; idx++) {
 740                DPAA_PMD_DEBUG("KG SCHEME DEL %d, handle =%p",
 741                        idx, dpaa_intf->scheme_handle[idx]);
 742                /* FM PCD KgSchemeDelete */
 743                ret = fm_pcd_kg_scheme_delete(dpaa_intf->scheme_handle[idx]);
 744                if (ret != E_OK) {
 745                        DPAA_PMD_ERR("fm_pcd_kg_scheme_delete: Failed");
 746                        return ret;
 747                }
 748                dpaa_intf->scheme_handle[idx] = NULL;
 749        }
 750        /* FM PCD NetEnvCharacteristicsDelete */
 751        ret = fm_pcd_net_env_characteristics_delete(dpaa_intf->netenv_handle);
 752        if (ret != E_OK) {
 753                DPAA_PMD_ERR("fm_pcd_net_env_characteristics_delete: Failed");
 754                return ret;
 755        }
 756        dpaa_intf->netenv_handle = NULL;
 757
 758        if (fif && fif->is_shared_mac) {
 759                ret = fm_port_enable(dpaa_intf->port_handle);
 760                if (ret != E_OK) {
 761                        DPAA_PMD_ERR("shared mac re-enable failed");
 762                        return ret;
 763                }
 764        }
 765
 766        /* FM PORT Close */
 767        fm_port_close(dpaa_intf->port_handle);
 768        dpaa_intf->port_handle = NULL;
 769
 770        /* Set scheme count to 0 */
 771        dpaa_intf->scheme_count = 0;
 772
 773        return 0;
 774}
 775
 776int dpaa_fm_config(struct rte_eth_dev *dev, uint64_t req_dist_set)
 777{
 778        struct dpaa_if *dpaa_intf = dev->data->dev_private;
 779        struct fman_if *fif = dev->process_private;
 780        int ret;
 781        unsigned int i = 0;
 782        PMD_INIT_FUNC_TRACE();
 783
 784        if (dpaa_intf->port_handle) {
 785                if (dpaa_fm_deconfig(dpaa_intf, fif))
 786                        DPAA_PMD_ERR("DPAA FM deconfig failed");
 787        }
 788
 789        if (!dev->data->nb_rx_queues)
 790                return 0;
 791
 792        if (dev->data->nb_rx_queues & (dev->data->nb_rx_queues - 1)) {
 793                DPAA_PMD_ERR("No of queues should be power of 2");
 794                return -1;
 795        }
 796
 797        dpaa_intf->nb_rx_queues = dev->data->nb_rx_queues;
 798
 799        /* Open FM Port and set it in port info */
 800        ret = set_fm_port_handle(dpaa_intf, req_dist_set, fif);
 801        if (ret) {
 802                DPAA_PMD_ERR("Set FM Port handle: Failed");
 803                return -1;
 804        }
 805
 806        if (fif->num_profiles) {
 807                for (i = 0; i < dpaa_intf->nb_rx_queues; i++)
 808                        dpaa_intf->rx_queues[i].vsp_id =
 809                                fm_default_vsp_id(fif);
 810
 811                i = 0;
 812        }
 813
 814        /* Set PCD netenv and scheme */
 815        if (req_dist_set) {
 816                ret = set_pcd_netenv_scheme(dpaa_intf, req_dist_set, fif);
 817                if (ret) {
 818                        DPAA_PMD_ERR("Set PCD NetEnv and Scheme dist: Failed");
 819                        goto unset_fm_port_handle;
 820                }
 821        }
 822        /* Set default netenv and scheme */
 823        if (!fif->is_shared_mac) {
 824                ret = set_default_scheme(dpaa_intf);
 825                if (ret) {
 826                        DPAA_PMD_ERR("Set PCD NetEnv and Scheme: Failed");
 827                        goto unset_pcd_netenv_scheme1;
 828                }
 829        }
 830
 831        /* Set Port PCD */
 832        ret = set_port_pcd(dpaa_intf);
 833        if (ret) {
 834                DPAA_PMD_ERR("Set Port PCD: Failed");
 835                goto unset_pcd_netenv_scheme;
 836        }
 837
 838        for (; i < fm_model.dev_count; i++)
 839                if (fm_model.device_order[i] == dpaa_intf->ifid)
 840                        return 0;
 841
 842        fm_model.device_order[fm_model.dev_count] = dpaa_intf->ifid;
 843        fm_model.dev_count++;
 844
 845        return 0;
 846
 847unset_pcd_netenv_scheme:
 848        unset_pcd_netenv_scheme(dpaa_intf);
 849
 850unset_pcd_netenv_scheme1:
 851        unset_pcd_netenv_scheme(dpaa_intf);
 852
 853unset_fm_port_handle:
 854        /* FM PORT Close */
 855        fm_port_close(dpaa_intf->port_handle);
 856        dpaa_intf->port_handle = NULL;
 857        return -1;
 858}
 859
 860int dpaa_fm_init(void)
 861{
 862        t_handle fman_handle;
 863        t_handle pcd_handle;
 864        t_fm_pcd_params fm_pcd_params = {0};
 865        /* Hard-coded : fman id 0 since one fman is present in LS104x */
 866        int fman_id = 0, ret;
 867        PMD_INIT_FUNC_TRACE();
 868
 869        dpaa_read_fm_config_from_file();
 870
 871        /* FM Open */
 872        fman_handle = fm_open(fman_id);
 873        if (!fman_handle) {
 874                DPAA_PMD_ERR("fm_open: Failed");
 875                return -1;
 876        }
 877
 878        /* FM PCD Open */
 879        fm_pcd_params.h_fm = fman_handle;
 880        fm_pcd_params.prs_support = true;
 881        fm_pcd_params.kg_support = true;
 882        pcd_handle = fm_pcd_open(&fm_pcd_params);
 883        if (!pcd_handle) {
 884                fm_close(fman_handle);
 885                DPAA_PMD_ERR("fm_pcd_open: Failed");
 886                return -1;
 887        }
 888
 889        /* FM PCD Enable */
 890        ret = fm_pcd_enable(pcd_handle);
 891        if (ret) {
 892                fm_close(fman_handle);
 893                fm_pcd_close(pcd_handle);
 894                DPAA_PMD_ERR("fm_pcd_enable: Failed");
 895                return -1;
 896        }
 897
 898        /* Set fman and pcd handle in fm info */
 899        fm_info.fman_handle = fman_handle;
 900        fm_info.pcd_handle = pcd_handle;
 901
 902        return 0;
 903}
 904
 905
 906/* De-initialization of FM */
 907int dpaa_fm_term(void)
 908{
 909        int ret;
 910
 911        PMD_INIT_FUNC_TRACE();
 912
 913        if (fm_info.pcd_handle && fm_info.fman_handle) {
 914                /* FM PCD Disable */
 915                ret = fm_pcd_disable(fm_info.pcd_handle);
 916                if (ret) {
 917                        DPAA_PMD_ERR("fm_pcd_disable: Failed");
 918                        return -1;
 919                }
 920
 921                /* FM PCD Close */
 922                fm_pcd_close(fm_info.pcd_handle);
 923                fm_info.pcd_handle = NULL;
 924        }
 925
 926        if (fm_info.fman_handle) {
 927                /* FM Close */
 928                fm_close(fm_info.fman_handle);
 929                fm_info.fman_handle = NULL;
 930        }
 931
 932        if (access(fm_log, F_OK) != -1) {
 933                ret = remove(fm_log);
 934                if (ret)
 935                        DPAA_PMD_ERR("File remove: Failed");
 936        }
 937        return 0;
 938}
 939
 940static int dpaa_port_vsp_configure(struct dpaa_if *dpaa_intf,
 941                uint8_t vsp_id, t_handle fman_handle,
 942                struct fman_if *fif)
 943{
 944        t_fm_vsp_params vsp_params;
 945        t_fm_buffer_prefix_content buf_prefix_cont;
 946        uint8_t mac_idx[] = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1};
 947        uint8_t idx = mac_idx[fif->mac_idx];
 948        int ret;
 949
 950        if (vsp_id == fif->base_profile_id && fif->is_shared_mac) {
 951                /* For shared interface, VSP of base
 952                 * profile is default pool located in kernel.
 953                 */
 954                dpaa_intf->vsp_bpid[vsp_id] = 0;
 955                return 0;
 956        }
 957
 958        if (vsp_id >= DPAA_VSP_PROFILE_MAX_NUM) {
 959                DPAA_PMD_ERR("VSP ID %d exceeds MAX number %d",
 960                        vsp_id, DPAA_VSP_PROFILE_MAX_NUM);
 961                return -1;
 962        }
 963
 964        memset(&vsp_params, 0, sizeof(vsp_params));
 965        vsp_params.h_fm = fman_handle;
 966        vsp_params.relative_profile_id = vsp_id;
 967        vsp_params.port_params.port_id = idx;
 968        if (fif->mac_type == fman_mac_1g) {
 969                vsp_params.port_params.port_type = e_FM_PORT_TYPE_RX;
 970        } else if (fif->mac_type == fman_mac_2_5g) {
 971                vsp_params.port_params.port_type = e_FM_PORT_TYPE_RX_2_5G;
 972        } else if (fif->mac_type == fman_mac_10g) {
 973                vsp_params.port_params.port_type = e_FM_PORT_TYPE_RX_10G;
 974        } else {
 975                DPAA_PMD_ERR("Mac type %d error", fif->mac_type);
 976                return -1;
 977        }
 978        vsp_params.ext_buf_pools.num_of_pools_used = 1;
 979        vsp_params.ext_buf_pools.ext_buf_pool[0].id =
 980                dpaa_intf->vsp_bpid[vsp_id];
 981        vsp_params.ext_buf_pools.ext_buf_pool[0].size =
 982                RTE_MBUF_DEFAULT_BUF_SIZE;
 983
 984        dpaa_intf->vsp_handle[vsp_id] = fm_vsp_config(&vsp_params);
 985        if (!dpaa_intf->vsp_handle[vsp_id]) {
 986                DPAA_PMD_ERR("fm_vsp_config error for profile %d", vsp_id);
 987                return -EINVAL;
 988        }
 989
 990        /* configure the application buffer (structure, size and
 991         * content)
 992         */
 993
 994        memset(&buf_prefix_cont, 0, sizeof(buf_prefix_cont));
 995
 996        buf_prefix_cont.priv_data_size = 16;
 997        buf_prefix_cont.data_align = 64;
 998        buf_prefix_cont.pass_prs_result = true;
 999        buf_prefix_cont.pass_time_stamp = true;
1000        buf_prefix_cont.pass_hash_result = false;
1001        buf_prefix_cont.pass_all_other_pcdinfo = false;
1002        buf_prefix_cont.manip_ext_space =
1003                RTE_PKTMBUF_HEADROOM - DPAA_MBUF_HW_ANNOTATION;
1004
1005        ret = fm_vsp_config_buffer_prefix_content(dpaa_intf->vsp_handle[vsp_id],
1006                                               &buf_prefix_cont);
1007        if (ret != E_OK) {
1008                DPAA_PMD_ERR("fm_vsp_config_buffer_prefix_content error for profile %d err: %d",
1009                             vsp_id, ret);
1010                return ret;
1011        }
1012
1013        /* initialize the FM VSP module */
1014        ret = fm_vsp_init(dpaa_intf->vsp_handle[vsp_id]);
1015        if (ret != E_OK) {
1016                DPAA_PMD_ERR("fm_vsp_init error for profile %d err:%d",
1017                         vsp_id, ret);
1018                return ret;
1019        }
1020
1021        return 0;
1022}
1023
1024int dpaa_port_vsp_update(struct dpaa_if *dpaa_intf,
1025                bool fmc_mode, uint8_t vsp_id, uint32_t bpid,
1026                struct fman_if *fif)
1027{
1028        int ret = 0;
1029        t_handle fman_handle;
1030
1031        if (!fif->num_profiles)
1032                return 0;
1033
1034        if (vsp_id >= fif->num_profiles)
1035                return 0;
1036
1037        if (dpaa_intf->vsp_bpid[vsp_id] == bpid)
1038                return 0;
1039
1040        if (dpaa_intf->vsp_handle[vsp_id]) {
1041                ret = fm_vsp_free(dpaa_intf->vsp_handle[vsp_id]);
1042                if (ret != E_OK) {
1043                        DPAA_PMD_ERR("Error fm_vsp_free: err %d vsp_handle[%d]",
1044                                     ret, vsp_id);
1045                        return ret;
1046                }
1047                dpaa_intf->vsp_handle[vsp_id] = 0;
1048        }
1049
1050        if (fmc_mode)
1051                fman_handle = fm_open(0);
1052        else
1053                fman_handle = fm_info.fman_handle;
1054
1055        dpaa_intf->vsp_bpid[vsp_id] = bpid;
1056
1057        return dpaa_port_vsp_configure(dpaa_intf, vsp_id, fman_handle, fif);
1058}
1059
1060int dpaa_port_vsp_cleanup(struct dpaa_if *dpaa_intf, struct fman_if *fif)
1061{
1062        int idx, ret;
1063
1064        for (idx = 0; idx < (uint8_t)fif->num_profiles; idx++) {
1065                if (dpaa_intf->vsp_handle[idx]) {
1066                        ret = fm_vsp_free(dpaa_intf->vsp_handle[idx]);
1067                        if (ret != E_OK) {
1068                                DPAA_PMD_ERR("Error fm_vsp_free: err %d"
1069                                             " vsp_handle[%d]", ret, idx);
1070                                return ret;
1071                        }
1072                }
1073        }
1074
1075        return E_OK;
1076}
1077