linux/drivers/misc/xilinx-ai-engine/ai-engine-rscmgr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Xilinx AI Engine partition resource manager
   4 *
   5 * Copyright (C) 2021 Xilinx, Inc.
   6 */
   7
   8#include "ai-engine-internal.h"
   9#include <linux/slab.h>
  10
  11/*
  12 * Macros for the AI engine resource bitmap element header
  13 */
  14#define AIE_RSC_BITMAP_TILETYPE_BITSHIFT        0U
  15#define AIE_RSC_BITMAP_TILETYPE_BITWIDTH        4U
  16#define AIE_RSC_BITMAP_MODTYPE_BITSHIFT         4U
  17#define AIE_RSC_BITMAP_MODTYPE_BITWIDTH         4U
  18#define AIE_RSC_BITMAP_RSCTYPE_BITSHIFT         8U
  19#define AIE_RSC_BITMAP_RSCTYPE_BITWIDTH         8U
  20#define AIE_RSC_BITMAP_LENU64_BITSHIFT          16U
  21#define AIE_RSC_BITMAP_LENU64_BITWIDTH          32U
  22
  23#define AIE_RSC_BITMAP_GEN_MASK(N) \
  24        GENMASK_ULL((AIE_RSC_BITMAP_##N ##_BITSHIFT + \
  25                     AIE_RSC_BITMAP_##N ##_BITWIDTH - 1), \
  26                    AIE_RSC_BITMAP_##N ##_BITSHIFT)
  27#define AIE_RSC_BITMAP_TILETYPE_MASK    AIE_RSC_BITMAP_GEN_MASK(TILETYPE)
  28#define AIE_RSC_BITMAP_MODTYPE_MASK     AIE_RSC_BITMAP_GEN_MASK(MODTYPE)
  29#define AIE_RSC_BITMAP_RSCTYPE_MASK     AIE_RSC_BITMAP_GEN_MASK(RSCTYPE)
  30#define AIE_RSC_BITMAP_LENU64_MASK      AIE_RSC_BITMAP_GEN_MASK(LENU64)
  31
  32#define AIE_RSC_BITMAP_HEAD_VAL(N, v) \
  33        (((v) & AIE_RSC_BITMAP_##N ##_MASK) >> AIE_RSC_BITMAP_##N ##_BITSHIFT)
  34
  35/*
  36 * enum for AI engine resource bitmap allocation types
  37 */
  38enum aie_rsc_alloc_type {
  39        AIE_RSC_ALLOC_STATIC = 0,
  40        AIE_RSC_ALLOC_AVAIL = 1,
  41        AIE_RSC_ALLOC_MAX = 2
  42};
  43
  44/**
  45 * struct aie_rsc_meta_header - struct of a resource bitmaps meta data header
  46 * @stat: statistics information of the bitmaps, such as number of bitmaps
  47 * @bitmap_off: offset to the start of the binary of the first bitmap element
  48 */
  49struct aie_rsc_meta_header {
  50        u64 stat;
  51        u64 bitmap_off;
  52};
  53
  54/**
  55 * struct aie_rsc_bitmap - struct of a resource bitmap element
  56 * @header: bitmap header, it contains the following information:
  57 *          tile type, module type, resource type, and the bitmap
  58 *          length.
  59 * @bitmap: the pointer of bitmap
  60 */
  61struct aie_rsc_bitmap {
  62        u64 header;
  63        u64 bitmap[0];
  64};
  65
  66/**
  67 * aie_dev_get_tile_attr - helper function to get tile attributes
  68 * @adev: AI engine device
  69 * @ttype: tile type
  70 * @return: attributes of an AI engine tile type
  71 */
  72static inline
  73struct aie_tile_attr *aie_dev_get_tile_attr(struct aie_device *adev,
  74                                            enum aie_tile_type ttype)
  75{
  76        return &adev->ttype_attr[ttype];
  77}
  78
  79/**
  80 * aie_dev_get_tile_rsc_attr - helper function to get resource attribute of a
  81 *                             tile type of an AI engine device
  82 * @adev: AI engine device
  83 * @ttype: tile type
  84 * @rtype: resource type
  85 * @return: attributes of an AI engine resource type of a tile type
  86 */
  87static inline const
  88struct aie_tile_rsc_attr *aie_dev_get_tile_rsc_attr(struct aie_device *adev,
  89                                                    enum aie_tile_type ttype,
  90                                                    enum aie_rsc_type rtype)
  91{
  92        return &adev->ttype_attr[ttype].rscs_attr[rtype];
  93}
  94
  95/**
  96 * aie_dev_get_mod_id - helper function to get module id of a module of a tile
  97 *                      type. The module ID can be used to indexing the resource
  98 *                      attributes of a module type of a tile type or indexing
  99 *                      resource status bitmaps.
 100 *
 101 * @adev: AI engine device
 102 * @ttype: tile type
 103 * @mod: module type
 104 * @return: module type index
 105 */
 106static int aie_dev_get_mod_id(struct aie_device *adev,
 107                              enum aie_tile_type ttype,
 108                              enum aie_module_type mod)
 109{
 110        struct aie_tile_attr *tattr = &adev->ttype_attr[ttype];
 111
 112        int ret;
 113
 114        if (ttype == AIE_TILE_TYPE_TILE)
 115                ret = AIE_MOD_ID(TILE, mod);
 116        else if (ttype == AIE_TILE_TYPE_SHIMPL)
 117                ret = AIE_MOD_ID(SHIMPL, mod);
 118        else
 119                ret = AIE_MOD_ID(SHIMNOC, mod);
 120
 121        if (ret < 0 || ret > tattr->num_mods)
 122                return -EINVAL;
 123
 124        return ret;
 125}
 126
 127/**
 128 * aie_dev_get_mod_rsc_attr - helper function to get resource attribute of a
 129 *                            module of an AI engine device
 130 * @adev: AI engine device
 131 * @ttype: tile type
 132 * @mod: module type
 133 * @rtype: resource type
 134 * @return: module type resource attributes
 135 */
 136static const
 137struct aie_mod_rsc_attr *aie_dev_get_mod_rsc_attr(struct aie_device *adev,
 138                                                  enum aie_tile_type ttype,
 139                                                  enum aie_module_type mod,
 140                                                  enum aie_rsc_type rtype)
 141{
 142        const struct aie_tile_rsc_attr *rsc = aie_dev_get_tile_rsc_attr(adev,
 143                                                                        ttype,
 144                                                                        rtype);
 145        const struct aie_mod_rsc_attr *mrsc = NULL;
 146        int mod_id = aie_dev_get_mod_id(adev, ttype, mod);
 147
 148        if (mod_id < 0)
 149                return NULL;
 150
 151        mrsc = &rsc->mod_attr[mod_id];
 152        if (mrsc && !mrsc->num_rscs)
 153                return NULL;
 154
 155        return mrsc;
 156}
 157
 158/**
 159 * aie_part_get_ttype_rsc_bitmaps - helper function to get bitmap of a resource
 160 *                                  with tile type, module type, and resource
 161 *                                  type
 162 *
 163 * @apart: AI engine partition
 164 * @ttype: tile type
 165 * @mod: module type
 166 * @rtype: resource type
 167 * @return: pointer to AI engine resource status bitmaps if resource is found,
 168 *          otherwise NULL
 169 */
 170static
 171struct aie_rsc_stat *aie_part_get_ttype_rsc_bitmaps(struct aie_partition *apart,
 172                                                    enum aie_tile_type ttype,
 173                                                    enum aie_module_type mod,
 174                                                    enum aie_rsc_type rtype)
 175{
 176        int mod_id;
 177        struct aie_mod_rscs *mrscs;
 178
 179        if (ttype >= AIE_TILE_TYPE_MAX)
 180                return NULL;
 181
 182        mod_id = aie_dev_get_mod_id(apart->adev, ttype, mod);
 183        if (mod_id < 0)
 184                return NULL;
 185
 186        if (rtype >= AIE_RSCTYPE_MAX)
 187                return NULL;
 188
 189        mrscs = apart->trscs[ttype].mod_rscs[rtype];
 190        if (!mrscs)
 191                return NULL;
 192
 193        return mrscs[mod_id].rscs_stat;
 194}
 195
 196/**
 197 * aie_part_get_rsc_bitmaps - helper function to get bitmap of a resource
 198 *
 199 * @apart: AI engine partition
 200 * @loc: tile location
 201 * @mod: module type
 202 * @rtype: resource type
 203 * @return: pointer to AI engine resource status bitmaps if resource is found,
 204 *          otherwise NULL
 205 */
 206static
 207struct aie_rsc_stat *aie_part_get_rsc_bitmaps(struct aie_partition *apart,
 208                                              struct aie_location loc,
 209                                              enum aie_module_type mod,
 210                                              enum aie_rsc_type rtype)
 211{
 212        u32 ttype = apart->adev->ops->get_tile_type(&loc);
 213
 214        return aie_part_get_ttype_rsc_bitmaps(apart, ttype, mod, rtype);
 215}
 216
 217/**
 218 * aie_part_get_mod_num_rscs - helper function to get number of resources
 219 *                             of a module of a tile
 220 *
 221 * @apart: AI engine partition
 222 * @loc: tile location
 223 * @mod: module type
 224 * @rtype: resource type
 225 * @return: number of max resources of a module of a tile
 226 */
 227static
 228int aie_part_get_mod_num_rscs(struct aie_partition *apart,
 229                              struct aie_location loc,
 230                              enum aie_module_type mod,
 231                              enum aie_rsc_type rtype)
 232{
 233        u32 ttype = apart->adev->ops->get_tile_type(&loc);
 234        const struct aie_mod_rsc_attr *mattr;
 235
 236        mattr = aie_dev_get_mod_rsc_attr(apart->adev, ttype, mod, rtype);
 237        if (!mattr)
 238                return 0;
 239
 240        return mattr->num_rscs;
 241}
 242
 243/**
 244 * aie_part_get_rsc_startbit - helper function to get the start bit of a
 245 *                             resource of a module of a tile.
 246 *
 247 * @apart: AI engine partition
 248 * @loc: tile location
 249 * @mod: module type
 250 * @rtype: resource type
 251 * @return: pointer to AI engine resource status bitmaps if resource is found,
 252 *          otherwise NULL
 253 *
 254 */
 255static
 256int aie_part_get_rsc_startbit(struct aie_partition *apart,
 257                              struct aie_location loc,
 258                              enum aie_module_type mod,
 259                              enum aie_rsc_type rtype)
 260{
 261        struct aie_device *adev = apart->adev;
 262        u32 ttype;
 263        const struct aie_mod_rsc_attr *mattr;
 264        int num_rows;
 265        struct aie_tile_attr *tattr;
 266
 267        ttype = adev->ops->get_tile_type(&loc);
 268
 269        mattr = aie_dev_get_mod_rsc_attr(adev, ttype, mod, rtype);
 270        if (!mattr)
 271                return -EINVAL;
 272
 273        num_rows = aie_part_get_tile_rows(apart, ttype);
 274        tattr = &adev->ttype_attr[ttype];
 275        return mattr->num_rscs *
 276               ((loc.col - apart->range.start.col) * num_rows +
 277                loc.row - tattr->start_row);
 278}
 279
 280/**
 281 * aie_part_adjust_loc - adjust relative tile location to partition to
 282 *                              absolute location in AI engine device
 283 * @apart: AI engine partition
 284 * @rloc: relative location in AI engine partition
 285 * @loc: returns absolute location in AI engine device
 286 * @return: 0 for success, negative value for failure
 287 */
 288static
 289int aie_part_adjust_loc(struct aie_partition *apart,
 290                        struct aie_location rloc, struct aie_location *loc)
 291{
 292        loc->col = rloc.col + apart->range.start.col;
 293        loc->row = rloc.row + apart->range.start.row;
 294
 295        if (aie_validate_location(apart, *loc) < 0) {
 296                dev_err(&apart->dev,
 297                        "invalid loc (%u,%u) in (%u,%u).\n",
 298                        rloc.col, rloc.row,
 299                        apart->range.size.col, apart->range.size.row);
 300                return -EINVAL;
 301        }
 302
 303        return 0;
 304}
 305
 306/**
 307 * aie_part_rscmgr_init() - initialize AI engine partition resource status
 308 *                          bitmaps
 309 * @apart: AI engine partition
 310 * @return: 0 for success, negative value for failure.
 311 *
 312 * This function will create the hardware resources status bitmaps for the whole
 313 * partition.
 314 * Each partition contains an array of hardware resources status bitmaps of all
 315 * defined tiles types.:
 316 * aie_partition
 317 *   |- trscs[<all_tile_types>]
 318 *       |-mod_rscs[<all_resources_types>]
 319 *         |-rscs_stat - resources status bitmaps of a module type of a tile
 320 *                       type of the AI engine partition.
 321 */
 322int aie_part_rscmgr_init(struct aie_partition *apart)
 323{
 324        struct aie_device *adev = apart->adev;
 325        u32 t;
 326
 327        for (t = AIE_TILE_TYPE_TILE; t < AIE_TILE_TYPE_MAX; t++) {
 328                struct aie_tile_rscs *trscs = &apart->trscs[t];
 329                struct aie_tile_attr *tattr;
 330                int num_rows, num_cols;
 331                u32 r;
 332
 333                /*
 334                 * SHIMNOC tile resource bitmaps reuse the SHIMPL resource
 335                 * bitmaps. In future, for DMA resources, SHIMNOC tile will
 336                 * have DMA resources bitmap which will be the unique to
 337                 * SHIMNOC tiles.
 338                 */
 339                if (t == AIE_TILE_TYPE_SHIMNOC) {
 340                        *trscs = apart->trscs[AIE_TILE_TYPE_SHIMPL];
 341                        continue;
 342                }
 343
 344                /*
 345                 * Get the number of rows of a tile type and the number
 346                 * of columns of the partition, which will be used to
 347                 * calculate the size of the bitmap is a resource.
 348                 */
 349                tattr = aie_dev_get_tile_attr(adev, t);
 350                num_rows = aie_part_get_tile_rows(apart, t);
 351                num_cols = apart->range.size.col;
 352
 353                for (r = AIE_RSCTYPE_PERF; r < AIE_RSCTYPE_MAX; r++) {
 354                        const struct aie_tile_rsc_attr *trsc_attr;
 355                        struct aie_mod_rscs *mod_rscs;
 356                        u32 m;
 357
 358                        trsc_attr = aie_dev_get_tile_rsc_attr(adev, t, r);
 359                        if (!trsc_attr)
 360                                continue;
 361
 362                        mod_rscs = kcalloc(tattr->num_mods,
 363                                           sizeof(*mod_rscs), GFP_KERNEL);
 364                        if (!mod_rscs) {
 365                                aie_part_rscmgr_finish(apart);
 366                                return -ENOMEM;
 367                        }
 368
 369                        trscs->mod_rscs[r] = mod_rscs;
 370                        for (m = 0 ; m < tattr->num_mods; m++) {
 371                                struct aie_rsc_stat *rscs_stat;
 372                                int num_mrscs = trsc_attr->mod_attr[m].num_rscs;
 373                                int ret, total_rscs;
 374
 375                                /*
 376                                 * if number of resources of this module type in
 377                                 * this tile type is 0, skip allocating bitmap
 378                                 * for the resource of this module type.
 379                                 */
 380                                if (!num_mrscs)
 381                                        continue;
 382
 383                                rscs_stat = kzalloc(sizeof(*rscs_stat),
 384                                                    GFP_KERNEL);
 385                                if (!rscs_stat) {
 386                                        aie_part_rscmgr_finish(apart);
 387                                        return -ENOMEM;
 388                                }
 389
 390                                mod_rscs[m].rscs_stat = rscs_stat;
 391                                total_rscs = num_mrscs * num_rows * num_cols;
 392                                /*
 393                                 * initialize bitmaps for static resources and
 394                                 * runtime allocated resources.
 395                                 */
 396                                ret = aie_resource_initialize(&rscs_stat->rbits,
 397                                                              total_rscs);
 398                                if (ret) {
 399                                        aie_part_rscmgr_finish(apart);
 400                                        return ret;
 401                                }
 402                                ret = aie_resource_initialize(&rscs_stat->sbits,
 403                                                              total_rscs);
 404                                if (ret) {
 405                                        aie_part_rscmgr_finish(apart);
 406                                        return ret;
 407                                }
 408                        }
 409                }
 410        }
 411
 412        /* Reserve resources for interrupts */
 413        return aie_part_set_intr_rscs(apart);
 414}
 415
 416/**
 417 * aie_part_rscmgr_finish() - uninitialize AI engine partition resource status
 418 *                            bitmaps.
 419 * @apart: AI engine partition
 420 */
 421void aie_part_rscmgr_finish(struct aie_partition *apart)
 422{
 423        struct aie_device *adev = apart->adev;
 424        u32 t;
 425
 426        for (t = AIE_TILE_TYPE_TILE; t < AIE_TILE_TYPE_MAX; t++) {
 427                struct aie_tile_rscs *trscs = &apart->trscs[t];
 428                struct aie_tile_attr *tattr;
 429                u32 r;
 430
 431                /* SHIMNOC reuses SHIMPL resources bitmap */
 432                if (t == AIE_TILE_TYPE_SHIMNOC)
 433                        continue;
 434
 435                tattr = aie_dev_get_tile_attr(adev, t);
 436                for (r = AIE_RSCTYPE_PERF; r < AIE_RSCTYPE_MAX; r++) {
 437                        struct aie_mod_rscs *mod_rscs;
 438                        u32 m;
 439
 440                        mod_rscs = trscs->mod_rscs[r];
 441                        if (!mod_rscs)
 442                                continue;
 443
 444                        for (m = 0 ; m < tattr->num_mods; m++) {
 445                                struct aie_rsc_stat *rscs_stat;
 446
 447                                rscs_stat = mod_rscs[m].rscs_stat;
 448                                if (!rscs_stat)
 449                                        continue;
 450
 451                                aie_resource_uninitialize(&rscs_stat->rbits);
 452                                aie_resource_uninitialize(&rscs_stat->sbits);
 453                        }
 454
 455                        kfree(mod_rscs);
 456                        trscs->mod_rscs[r] = NULL;
 457                }
 458        }
 459}
 460
 461/**
 462 * aie_part_rscmgr_reset() - reset AI engine partition resource status bitmaps
 463 *
 464 * @apart: AI engine partition
 465 *
 466 * This function expect caller to lock the partition before calling this
 467 * function.
 468 */
 469void aie_part_rscmgr_reset(struct aie_partition *apart)
 470{
 471        struct aie_device *adev = apart->adev;
 472        u32 t;
 473
 474        for (t = AIE_TILE_TYPE_TILE; t < AIE_TILE_TYPE_MAX; t++) {
 475                struct aie_tile_rscs *trscs = &apart->trscs[t];
 476                struct aie_tile_attr *tattr;
 477                u32 r;
 478
 479                /* SHIMNOC reuses SHIMPL resources bitmap */
 480                if (t == AIE_TILE_TYPE_SHIMNOC)
 481                        continue;
 482
 483                tattr = aie_dev_get_tile_attr(adev, t);
 484                for (r = AIE_RSCTYPE_PERF; r < AIE_RSCTYPE_MAX; r++) {
 485                        struct aie_mod_rscs *mod_rscs;
 486                        u32 m;
 487
 488                        mod_rscs = trscs->mod_rscs[r];
 489                        if (!mod_rscs)
 490                                continue;
 491
 492                        for (m = 0 ; m < tattr->num_mods; m++) {
 493                                struct aie_rsc_stat *rscs_stat;
 494
 495                                rscs_stat = mod_rscs[m].rscs_stat;
 496                                if (!rscs_stat)
 497                                        continue;
 498
 499                                aie_resource_clear_all(&rscs_stat->rbits);
 500                                aie_resource_clear_all(&rscs_stat->sbits);
 501                        }
 502                }
 503        }
 504
 505        /* Always reserve resources for interrupt */
 506        (void)aie_part_set_intr_rscs(apart);
 507}
 508
 509/**
 510 * aie_part_rscmgr_rsc_req() - request a type of resource from a module of a
 511 *                             tile of an AI engine partition
 512 *
 513 * @apart: AI engine partition
 514 * @user_args: user resource request arguments
 515 *
 516 * @return: 0 for success, negative value for failure
 517 *
 518 * This function will check if there the specified number of free resources
 519 * available. If yes, allocated the specified number of resources.
 520 */
 521long aie_part_rscmgr_rsc_req(struct aie_partition *apart,
 522                             void __user *user_args)
 523{
 524        struct aie_rsc_req_rsp args;
 525        struct aie_location loc;
 526        struct aie_rsc_stat *rstat;
 527        long ret;
 528        int mod_num_rscs, start_bit;
 529        struct aie_rsc *rscs;
 530
 531        if (copy_from_user(&args, user_args, sizeof(args)))
 532                return -EFAULT;
 533
 534        if (!args.rscs) {
 535                dev_err(&apart->dev,
 536                        "invalid resource request, empty resources list.\n");
 537                return -EINVAL;
 538        }
 539
 540        ret = aie_part_adjust_loc(apart, args.req.loc, &loc);
 541        if (ret < 0)
 542                return ret;
 543
 544        if (args.req.type > AIE_RSCTYPE_MAX) {
 545                dev_err(&apart->dev,
 546                        "invalid resource request, invalid resource type %d.\n",
 547                        args.req.type);
 548                return -EINVAL;
 549        }
 550
 551        rstat = aie_part_get_rsc_bitmaps(apart, loc, args.req.mod,
 552                                         args.req.type);
 553        start_bit = aie_part_get_rsc_startbit(apart, loc, args.req.mod,
 554                                              args.req.type);
 555        if (!rstat || start_bit < 0) {
 556                dev_err(&apart->dev,
 557                        "invalid resource request(%u,%u), mod:%u, rsc:%u.\n",
 558                        args.req.loc.col, args.req.loc.row, args.req.mod,
 559                        args.req.type);
 560                return -EINVAL;
 561        }
 562
 563        mod_num_rscs = aie_part_get_mod_num_rscs(apart, loc, args.req.mod,
 564                                                 args.req.type);
 565        if (!args.req.num_rscs || args.req.num_rscs > mod_num_rscs) {
 566                dev_err(&apart->dev,
 567                        "invalid resource req(%u,%u),mod:%u,rsc:%u,expect=%u,max=%u.\n",
 568                        args.req.loc.col, args.req.loc.row, args.req.mod,
 569                        args.req.type, args.req.num_rscs, mod_num_rscs);
 570                return -EINVAL;
 571        }
 572
 573        rscs = kmalloc_array(args.req.num_rscs, sizeof(*rscs), GFP_KERNEL);
 574        if (!rscs)
 575                return -ENOMEM;
 576
 577        ret = mutex_lock_interruptible(&apart->mlock);
 578        if (ret) {
 579                kfree(rscs);
 580                return ret;
 581        }
 582
 583        /*
 584         * There can be some resources needs to be contiguous, such as combo events.
 585         * It needs to be 0,1; 2,3; or 0,1,2; or 0,1,2,3
 586         */
 587        if (!(args.req.flag & XAIE_RSC_PATTERN_BLOCK)) {
 588                ret = aie_resource_get_common_avail(&rstat->rbits, &rstat->sbits,
 589                                                    start_bit,
 590                                                    args.req.num_rscs,
 591                                                    mod_num_rscs, rscs);
 592        } else {
 593                ret = aie_resource_get_common_pattern_region(&rstat->rbits,
 594                                                             &rstat->sbits,
 595                                                             start_bit,
 596                                                             args.req.num_rscs,
 597                                                             mod_num_rscs,
 598                                                             rscs);
 599        }
 600        mutex_unlock(&apart->mlock);
 601
 602        if (ret < 0) {
 603                if (!(args.req.flag & XAIE_RSC_PATTERN_BLOCK)) {
 604                        dev_warn(&apart->dev,
 605                                 "invalid resource req(%u,%u),mod:%u,rsc:%u,expect=%u not avail.\n",
 606                                args.req.loc.col, args.req.loc.row,
 607                                args.req.mod, args.req.type,
 608                                args.req.num_rscs);
 609                } else {
 610                        dev_warn(&apart->dev,
 611                                 "invalid contiguous resource req(%u,%u),mod:%u,rsc:%u,expect=%u not avail.\n",
 612                                args.req.loc.col, args.req.loc.row,
 613                                args.req.mod, args.req.type, args.req.num_rscs);
 614                }
 615                kfree(rscs);
 616                return ret;
 617        }
 618
 619        if (copy_to_user((void __user *)args.rscs, rscs,
 620                         sizeof(*rscs) * args.req.num_rscs))
 621                ret = -EFAULT;
 622        else
 623                ret = 0;
 624
 625        kfree(rscs);
 626        return ret;
 627}
 628
 629/**
 630 * aie_part_rscmgr_rsc_clearbit() - clear resource status of a module of a
 631 *                                  tile of an AI engine partition
 632 *
 633 * @apart: AI engine partition
 634 * @user_args: user resource release arguments
 635 * @is_release: true to clear the status from both runtime and static bitmaps
 636 *
 637 * @return: 0 for success, negative value for failure
 638 *
 639 * This function will clear the status of a resource of both runtime status
 640 * bitmap and static status bitmap or both based on the @is_release setting.
 641 */
 642static long aie_part_rscmgr_rsc_clearbit(struct aie_partition *apart,
 643                                         void __user *user_args,
 644                                         bool is_release)
 645{
 646        struct aie_rsc args;
 647        struct aie_location loc, rloc;
 648        struct aie_rsc_stat *rstat;
 649        long ret;
 650        int mod_num_rscs, start_bit;
 651
 652        if (copy_from_user(&args, user_args, sizeof(args)))
 653                return -EFAULT;
 654
 655        rloc.col = (u32)(args.loc.col & 0xFF);
 656        rloc.row = (u32)(args.loc.row & 0xFF);
 657        ret = aie_part_adjust_loc(apart, rloc, &loc);
 658        if (ret < 0)
 659                return ret;
 660
 661        if (args.type > AIE_RSCTYPE_MAX) {
 662                dev_err(&apart->dev,
 663                        "invalid resource to release, invalid resource type %d.\n",
 664                        args.type);
 665                return -EINVAL;
 666        }
 667
 668        rstat = aie_part_get_rsc_bitmaps(apart, loc, args.mod, args.type);
 669        start_bit = aie_part_get_rsc_startbit(apart, loc, args.mod,
 670                                              args.type);
 671        if (!rstat || start_bit < 0) {
 672                dev_err(&apart->dev,
 673                        "invalid resource to release(%u,%u),mod:%u,rsc:%u.\n",
 674                        rloc.col, rloc.row, args.mod, args.type);
 675                return -EINVAL;
 676        }
 677
 678        mod_num_rscs = aie_part_get_mod_num_rscs(apart, loc, args.mod,
 679                                                 args.type);
 680        if (args.id > mod_num_rscs) {
 681                dev_err(&apart->dev,
 682                        "invalid resource to release(%u,%u),mod:%u,rsc:%u,id=%u.\n",
 683                        rloc.col, rloc.row, args.mod, args.type, args.id);
 684                return -EINVAL;
 685        }
 686
 687        ret = mutex_lock_interruptible(&apart->mlock);
 688        if (ret)
 689                return ret;
 690
 691        if (!aie_resource_testbit(&rstat->rbits, start_bit + args.id)) {
 692                dev_err(&apart->dev,
 693                        "invalid resource to release(%u,%u),mod:%u,rsc:%u,id=%u. not requested\n",
 694                        rloc.col, rloc.row, args.mod, args.type, args.id);
 695                mutex_unlock(&apart->mlock);
 696                return -EINVAL;
 697        }
 698
 699        aie_resource_clear(&rstat->rbits, start_bit + args.id, 1);
 700        if (is_release)
 701                aie_resource_clear(&rstat->sbits, start_bit + args.id, 1);
 702
 703        mutex_unlock(&apart->mlock);
 704
 705        return 0;
 706}
 707
 708/**
 709 * aie_part_rscmgr_rsc_release() - release resource of a module of a tile of
 710 *                                 an AI engine partition
 711 *
 712 * @apart: AI engine partition
 713 * @user_args: user resource releasearguments
 714 *
 715 * @return: 0 for success, negative value for failure
 716 *
 717 * This function will clear the bit of the resource runtime and static status
 718 * bitmap.
 719 */
 720long aie_part_rscmgr_rsc_release(struct aie_partition *apart,
 721                                 void __user *user_args)
 722{
 723        return aie_part_rscmgr_rsc_clearbit(apart, user_args, true);
 724}
 725
 726/**
 727 * aie_part_rscmgr_rsc_free() - free resource of a module of a tile of an AI
 728 *                              engine partition
 729 *
 730 * @apart: AI engine partition
 731 * @user_args: user resource free arguments
 732 *
 733 * @return: 0 for success, negative value for failure
 734 *
 735 * This function will clear the bit of the resource runtime status bitmap.
 736 */
 737long aie_part_rscmgr_rsc_free(struct aie_partition *apart,
 738                              void __user *user_args)
 739{
 740        return aie_part_rscmgr_rsc_clearbit(apart, user_args, false);
 741}
 742
 743/**
 744 * aie_part_rscmgr_rsc_req_specific() - request for specific resource of a
 745 *                                      module of a tile of an AI engine
 746 *                                      partition
 747 *
 748 * @apart: AI engine partition
 749 * @user_args: user resource free arguments
 750 *
 751 * @return: 0 for success, negative value for failure
 752 *
 753 * This function requires the specified resource is set in the static
 754 * status bitmap
 755 */
 756long aie_part_rscmgr_rsc_req_specific(struct aie_partition *apart,
 757                                      void __user *user_args)
 758{
 759        struct aie_rsc args;
 760        struct aie_location loc, rloc;
 761        struct aie_rsc_stat *rstat;
 762        long ret;
 763        int mod_num_rscs, start_bit;
 764
 765        if (copy_from_user(&args, user_args, sizeof(args)))
 766                return -EFAULT;
 767
 768        rloc.col = (u32)(args.loc.col & 0xFF);
 769        rloc.row = (u32)(args.loc.row & 0xFF);
 770        ret = aie_part_adjust_loc(apart, rloc, &loc);
 771        if (ret < 0)
 772                return ret;
 773
 774        if (args.type > AIE_RSCTYPE_MAX) {
 775                dev_err(&apart->dev,
 776                        "invalid resource to request, invalid resource type %d.\n",
 777                        args.type);
 778                return -EINVAL;
 779        }
 780
 781        rstat = aie_part_get_rsc_bitmaps(apart, loc, args.mod, args.type);
 782        start_bit = aie_part_get_rsc_startbit(apart, loc, args.mod,
 783                                              args.type);
 784        if (!rstat || start_bit < 0) {
 785                dev_err(&apart->dev,
 786                        "invalid resource to request(%u,%u),mod:%u,rsc:%u.\n",
 787                        rloc.col, rloc.row, args.mod, args.type);
 788                return -EINVAL;
 789        }
 790
 791        mod_num_rscs = aie_part_get_mod_num_rscs(apart, loc, args.mod,
 792                                                 args.type);
 793        if (args.id > mod_num_rscs) {
 794                dev_err(&apart->dev,
 795                        "invalid resource to request(%u,%u),mod:%u, rsc:%u,id=%u.\n",
 796                        rloc.col, rloc.row, args.mod, args.type, args.id);
 797                return -EINVAL;
 798        }
 799
 800        ret = mutex_lock_interruptible(&apart->mlock);
 801        if (ret)
 802                return ret;
 803
 804        /* Check if the resource is in the runtime status bitmap */
 805        if (aie_resource_testbit(&rstat->rbits, start_bit + args.id)) {
 806                dev_err(&apart->dev,
 807                        "invalid resource to request(%u,%u),mod:%u,rsc:%u,id=%u, resource in use.\n",
 808                        rloc.col, rloc.row, args.mod, args.type, args.id);
 809                mutex_unlock(&apart->mlock);
 810                return -EBUSY;
 811        }
 812
 813        aie_resource_set(&rstat->rbits, start_bit + args.id, 1);
 814
 815        mutex_unlock(&apart->mlock);
 816
 817        return 0;
 818}
 819
 820/**
 821 * aie_part_rscmgr_rsc_check_avail() - check how many resources vailable for
 822 *                                     the specified resource type
 823 *
 824 * @apart: AI engine partition
 825 * @user_args: user resource free arguments
 826 *
 827 * @return: 0 for success, negative value for failure
 828 *
 829 * This function requires the specified resource is set in the static
 830 * status bitmap
 831 */
 832long aie_part_rscmgr_rsc_check_avail(struct aie_partition *apart,
 833                                     void __user *user_args)
 834{
 835        struct aie_rsc_stat *rstat;
 836        struct aie_location loc;
 837        long ret;
 838        int mod_num_rscs, start_bit;
 839        struct aie_rsc_req args;
 840
 841        if (copy_from_user(&args, user_args, sizeof(args)))
 842                return -EFAULT;
 843
 844        ret = aie_part_adjust_loc(apart, args.loc, &loc);
 845        if (ret < 0)
 846                return ret;
 847
 848        if (args.type > AIE_RSCTYPE_MAX) {
 849                dev_err(&apart->dev,
 850                        "invalid resource to request, invalid resource type %d.\n",
 851                        args.type);
 852                return -EINVAL;
 853        }
 854
 855        rstat = aie_part_get_rsc_bitmaps(apart, loc, args.mod, args.type);
 856        start_bit = aie_part_get_rsc_startbit(apart, loc, args.mod,
 857                                              args.type);
 858        if (!rstat || start_bit < 0) {
 859                dev_err(&apart->dev,
 860                        "invalid resource to request(%u,%u),mod:%u,rsc:%u.\n",
 861                        args.loc.col, args.loc.row, args.mod, args.type);
 862                return -EINVAL;
 863        }
 864
 865        mod_num_rscs = aie_part_get_mod_num_rscs(apart, loc, args.mod,
 866                                                 args.type);
 867        ret = mutex_lock_interruptible(&apart->mlock);
 868        if (ret)
 869                return ret;
 870
 871        args.num_rscs = aie_resource_check_common_avail(&rstat->rbits,
 872                                                        &rstat->sbits,
 873                                                        start_bit,
 874                                                        mod_num_rscs);
 875        mutex_unlock(&apart->mlock);
 876
 877        if (copy_to_user(user_args, &args, sizeof(args)))
 878                return -EFAULT;
 879
 880        return 0;
 881}
 882
 883/**
 884 * aie_part_rscmgr_get_ungated_bc_mods() - find the ungated modules of the full
 885 *                                         partition and fill in the locations
 886 *                                         information to the resources array.
 887 * @apart: AI engine partition
 888 * @num_rscs: number of broadcast resources, each module of a tile has a
 889 *            broadcast resource in this array.
 890 * @onum_rscs: returns the number of actual ungated broadcast resources of the
 891 *             whole partition.
 892 *
 893 * @rscs: broadcast resources array
 894 * @return: 0 for success, negative value for failure
 895 */
 896static int aie_part_rscmgr_get_ungated_bc_mods(struct aie_partition *apart,
 897                                               u32 num_rscs, u32 *onum_rscs,
 898                                               struct aie_rsc *rscs)
 899{
 900        struct aie_device *adev = apart->adev;
 901        u32 c, r, i = 0;
 902
 903        for (c = 0; c < apart->range.size.col; c++) {
 904                for (r = 0; r < apart->range.size.row; r++) {
 905                        struct aie_location l;
 906                        u32 ttype, m;
 907                        const struct aie_tile_attr *tattr;
 908                        const struct aie_tile_rsc_attr *rattr;
 909                        enum aie_rsc_type rtype = AIE_RSCTYPE_BROADCAST;
 910
 911                        l.col = apart->range.start.col + c;
 912                        l.row = r;
 913                        ttype = adev->ops->get_tile_type(&l);
 914                        tattr = &adev->ttype_attr[ttype];
 915                        rattr = &tattr->rscs_attr[rtype];
 916                        for (m = 0; m < tattr->num_mods; m++) {
 917                                /*
 918                                 * if module doesn't have broadcast channel,
 919                                 * skipped. This is not the case today.
 920                                 */
 921                                if (!rattr->mod_attr[m].num_rscs)
 922                                        continue;
 923                                /* Check if the broadcast resource is gated */
 924                                if (aie_part_check_clk_enable_loc(apart, &l)) {
 925                                        if (i >= num_rscs) {
 926                                                dev_err(&apart->dev,
 927                                                        "failed to returns all ungated tiles, not enough resource elements.\n");
 928                                                return -EINVAL;
 929                                        }
 930                                        rscs[i].loc.col = (u8)(c & 0xFF);
 931                                        rscs[i].loc.row = (u8)(r & 0xFF);
 932                                        rscs[i].mod = tattr->mods[m];
 933                                        i++;
 934                                }
 935                        }
 936                }
 937        }
 938
 939        *onum_rscs = i;
 940        return 0;
 941}
 942
 943/**
 944 * aie_part_rscmgr_get_or_bc_stat() - get OR the broadcast resources stat of
 945 *                                    specified modules in the specified
 946 *                                    resources array.
 947 *
 948 * @apart: AI engine partition
 949 * @num_rscs: number of broadcast resources, every module has one broadcast
 950 *            resource
 951 * @rscs: array of broadcast resources, each element contains the tile
 952 *        location and module information of the broadcast channel
 953 * @runtime_only: true to only check the runtime allocated resources bitmap,
 954 *                false to check both runtime and statically allocated resource
 955 *                bitmaps.
 956 * @or_stat: returns result of OR all the modules broadcast resources status
 957 * @return: 0 for success, negative value for failure
 958 */
 959static int aie_part_rscmgr_get_or_bc_stat(struct aie_partition *apart,
 960                                          u32 num_rscs, struct aie_rsc *rscs,
 961                                          bool runtime_only,
 962                                          unsigned long *or_stat)
 963{
 964        u32 i;
 965
 966        *or_stat = 0;
 967        for (i = 0; i < num_rscs; i++) {
 968                struct aie_location l;
 969                struct aie_rsc_stat *rstat;
 970                int mod_num_rscs, start_bit;
 971
 972                l.col = apart->range.start.col + rscs[i].loc.col;
 973                l.row = rscs[i].loc.row;
 974                rstat = aie_part_get_rsc_bitmaps(apart, l, rscs[i].mod,
 975                                                 AIE_RSCTYPE_BROADCAST);
 976                start_bit = aie_part_get_rsc_startbit(apart, l, rscs[i].mod,
 977                                                      AIE_RSCTYPE_BROADCAST);
 978                if (!rstat || start_bit < 0) {
 979                        dev_err(&apart->dev,
 980                                "failed to get broadcast bitmap for[%u]:tile(%u,%u), mod=%u.\n",
 981                                i, rscs[i].loc.col, rscs[i].loc.row,
 982                                rscs[i].mod);
 983                        return -EINVAL;
 984                }
 985                mod_num_rscs = aie_part_get_mod_num_rscs(apart, l, rscs[i].mod,
 986                                                         AIE_RSCTYPE_BROADCAST);
 987                *or_stat |= aie_resource_or_get_valueul(&rstat->rbits,
 988                                                        start_bit,
 989                                                        mod_num_rscs);
 990                if (!runtime_only)
 991                        *or_stat |= aie_resource_or_get_valueul(&rstat->sbits,
 992                                                                start_bit,
 993                                                                mod_num_rscs);
 994        }
 995
 996        return 0;
 997}
 998
 999/**
1000 * aie_part_rscmgr_get_common_bc() - get common broadcast id of specified
1001 *                                   modules in the specified resources array.
1002 *
1003 * @apart: AI engine partition
1004 * @num_rscs: number of broadcast resources, every module has one broadcast
1005 *            resource
1006 * @rscs: array of broadcast resources, each element contains the tile
1007 *        location and module information of the broadcast channel
1008 * @return: common broadcast channel id for success, negative value for failure
1009 *
1010 * This function checks both runtime and static allocated resources bitmap.
1011 */
1012static int aie_part_rscmgr_get_common_bc(struct aie_partition *apart,
1013                                         u32 num_rscs, struct aie_rsc *rscs)
1014{
1015        unsigned long or_stat, b;
1016        int ret;
1017        struct aie_location l;
1018        int mod_num_rscs;
1019
1020        l.col = apart->range.start.col + (u32)rscs[0].loc.row;
1021        l.row = (u32)rscs[0].loc.row;
1022
1023        ret = aie_part_rscmgr_get_or_bc_stat(apart, num_rscs, rscs, false,
1024                                             &or_stat);
1025        if (ret)
1026                return ret;
1027
1028        mod_num_rscs = aie_part_get_mod_num_rscs(apart, l, rscs[0].mod,
1029                                                 AIE_RSCTYPE_BROADCAST);
1030        b = bitmap_find_next_zero_area(&or_stat, mod_num_rscs, 0, 1, 0);
1031        if (b >= mod_num_rscs)
1032                return -EINVAL;
1033
1034        return (int)b;
1035}
1036
1037/**
1038 * aie_part_rscmgr_check_common_bc() - validate the specified common broadcast
1039 *                                     id in the specified modules in the
1040 *                                     specified resources array.
1041 *
1042 * @apart: AI engine partition
1043 * @bc: broadcast channel id to check
1044 * @num_rscs: number of broadcast resources, every module has one broadcast
1045 *            resource
1046 * @rscs: array of broadcast resources, each element contains the tile
1047 *        location and module information of the broadcast channel
1048 * @return: 0 if the specified broadcast channel id is available for all the
1049 *          specified modules, negative value for failure
1050 *
1051 * This function only checks runtime allocated resources bitmap.
1052 */
1053static int aie_part_rscmgr_check_common_bc(struct aie_partition *apart,
1054                                           u32 bc, u32 num_rscs,
1055                                           struct aie_rsc *rscs)
1056{
1057        unsigned long or_stat;
1058        int ret;
1059        struct aie_location l;
1060        int mod_num_rscs;
1061
1062        l.col = apart->range.start.col + (u32)rscs[0].loc.row;
1063        l.row = (u32)rscs[0].loc.row;
1064
1065        mod_num_rscs = aie_part_get_mod_num_rscs(apart, l, rscs[0].mod,
1066                                                 AIE_RSCTYPE_BROADCAST);
1067        if (bc > mod_num_rscs) {
1068                dev_err(&apart->dev,
1069                        "invalid specified broadcast id %u, max is %u.\n",
1070                        bc, mod_num_rscs);
1071                return -EINVAL;
1072        }
1073
1074        ret = aie_part_rscmgr_get_or_bc_stat(apart, num_rscs, rscs, true,
1075                                             &or_stat);
1076        if (ret)
1077                return ret;
1078
1079        if (test_bit(bc, &or_stat)) {
1080                dev_err(&apart->dev,
1081                        "specified broadcast id %u is occupied.\n", bc);
1082                return -EBUSY;
1083        }
1084
1085        return 0;
1086}
1087
1088/**
1089 * aie_part_rscmgr_check_rscs_modules() - validate the modules of the array of
1090 *                                      input resources
1091 *
1092 * @apart: AI engine partition
1093 * @num_rscs: number of resources
1094 * @rscs: array of resources, each element contains the tile
1095 *        location and module information of the resource
1096 * @return: 0 if the modules of all the resources are valid, negative value
1097 *          for failure
1098 *
1099 * This function validate the modules and the tiles of the resources, and
1100 * check if resource module is gated.
1101 */
1102static int aie_part_rscmgr_check_rscs_modules(struct aie_partition *apart,
1103                                              u32 num_rscs,
1104                                              struct aie_rsc *rscs)
1105{
1106        struct aie_device *adev = apart->adev;
1107        u32 i;
1108
1109        for (i = 0; i < num_rscs; i++) {
1110                struct aie_location l;
1111
1112                l.col = apart->range.start.col + rscs[i].loc.col;
1113                l.row = rscs[i].loc.row;
1114                /* validate tile location */
1115                if (aie_validate_location(apart, l)) {
1116                        dev_err(&apart->dev,
1117                                "failed resource check tile(%u,%u) invalid.\n",
1118                                        rscs[i].loc.col, rscs[i].loc.row);
1119                        return -EINVAL;
1120                }
1121
1122                /* validate module */
1123                if (aie_dev_get_mod_id(adev, adev->ops->get_tile_type(&l),
1124                                       rscs[i].mod) < 0) {
1125                        dev_err(&apart->dev,
1126                                "failed resource check, tile(%u,%u) mod %u invalid.\n",
1127                                        rscs[i].loc.col, rscs[i].loc.row,
1128                                        rscs[i].mod);
1129                        return -EINVAL;
1130                }
1131
1132                /* check if the resource module is gated */
1133                if (!aie_part_check_clk_enable_loc(apart, &l)) {
1134                        dev_err(&apart->dev,
1135                                "failed resource check, tile(%u,%u) mod=%u is gated.\n",
1136                                rscs[i].loc.col, rscs[i].loc.row,
1137                                rscs[i].mod);
1138                        return -EINVAL;
1139                }
1140        }
1141
1142        return 0;
1143}
1144
1145/**
1146 * aie_part_rscmgr_set_tile_broadcast() - set broadcast channel in use
1147 *                                        of a module of a tile
1148 *
1149 * @apart: AI engine partition
1150 * @loc: tile location
1151 * @mod: module
1152 * @id: broadcast channel id
1153 * @return: 0 for success, negative value for failure
1154 *
1155 * This function will set the bit of the specified broadcast channel in the
1156 * runtime broadcast bitmap of the specified module of the specified tile.
1157 */
1158int aie_part_rscmgr_set_tile_broadcast(struct aie_partition *apart,
1159                                       struct aie_location loc,
1160                                       enum aie_module_type mod, uint32_t id)
1161{
1162        struct aie_rsc_stat *rstat;
1163        int start_bit;
1164
1165        rstat = aie_part_get_rsc_bitmaps(apart, loc, mod,
1166                                         AIE_RSCTYPE_BROADCAST);
1167        /* bitmap pointer cannot be NULL. */
1168        if (WARN_ON(!rstat || !rstat->rbits.bitmap))
1169                return -EFAULT;
1170
1171        start_bit = aie_part_get_rsc_startbit(apart, loc, mod,
1172                                              AIE_RSCTYPE_BROADCAST);
1173        aie_resource_set(&rstat->rbits, start_bit + id, 1);
1174
1175        return 0;
1176}
1177
1178/**
1179 * aie_part_rscmgr_get_broadcast() - get common broadcast channel of
1180 *                                   the specified modules or the whole
1181 *                                   partition.
1182 *
1183 * @apart: AI engine partition
1184 * @user_args: user resource free arguments
1185 *
1186 * @return: 0 for success, negative value for failure
1187 *
1188 * This function get a common broadcast channel for the specified set
1189 * of AI engine modules in the resources array. If the any of the input set of
1190 * tiles is gated, it will return failure. This ioctl will not check the
1191 * connection of the input modules set.
1192 * The driver will fill in the resource ID with the assigned broadcast channel
1193 * ID of the resources array.
1194 * If the XAIE_BROADCAST_ALL is set in the request flag, it will get the
1195 * broadcast channel for all the ungated tiles of the partition.
1196 * If a particular broadcast channel id is specified in the request, if will
1197 * check if the channel is available for the specified modules, or the whole
1198 * partition depends on if XAIE_BROADCAST_ALL is set.
1199 */
1200long aie_part_rscmgr_get_broadcast(struct aie_partition *apart,
1201                                   void __user *user_args)
1202{
1203        struct aie_rsc_bc_req args;
1204        struct aie_rsc *rscs;
1205        u32 i;
1206        long ret;
1207
1208        if (copy_from_user(&args, user_args, sizeof(args)))
1209                return -EFAULT;
1210
1211        rscs = kmalloc_array(args.num_rscs, sizeof(*rscs), GFP_KERNEL);
1212        if (!rscs)
1213                return -ENOMEM;
1214
1215        if (!(args.flag & XAIE_BROADCAST_ALL)) {
1216                if (copy_from_user(rscs, (void __user *)args.rscs,
1217                                   sizeof(*rscs) * args.num_rscs)) {
1218                        kfree(rscs);
1219                        return -EFAULT;
1220                }
1221        }
1222
1223        ret = mutex_lock_interruptible(&apart->mlock);
1224        if (ret) {
1225                kfree(rscs);
1226                return ret;
1227        }
1228
1229        if (args.flag & XAIE_BROADCAST_ALL)
1230                /*
1231                 * It is to broadcast to the whole partition.
1232                 * Get all the ungated modules.
1233                 */
1234                ret = aie_part_rscmgr_get_ungated_bc_mods(apart, args.num_rscs,
1235                                                          &args.num_rscs,
1236                                                          rscs);
1237        else
1238                /*
1239                 * validate tiles and modules, and check if there are modules
1240                 * gated
1241                 */
1242                ret = aie_part_rscmgr_check_rscs_modules(apart, args.num_rscs,
1243                                                         rscs);
1244        if (ret)
1245                goto error;
1246
1247        /* find the common broadcast signal among the specified modules */
1248        if (args.id == XAIE_BROADCAST_ID_ANY) {
1249                ret = aie_part_rscmgr_get_common_bc(apart, args.num_rscs, rscs);
1250                if (ret >= 0) {
1251                        args.id = (u32)ret;
1252                        ret = 0;
1253                } else {
1254                        dev_warn(&apart->dev, "no available broadcast channel.\n");
1255                }
1256        } else {
1257                ret = aie_part_rscmgr_check_common_bc(apart, args.id,
1258                                                      args.num_rscs,
1259                                                      rscs);
1260        }
1261        if (ret)
1262                goto error;
1263
1264        /* set the broadcast channel resource runtime status bit */
1265        for (i = 0; i < args.num_rscs; i++) {
1266                struct aie_location l;
1267
1268                l.col = apart->range.start.col + rscs[i].loc.col;
1269                l.row = rscs[i].loc.row;
1270                ret = aie_part_rscmgr_set_tile_broadcast(apart, l, rscs[i].mod,
1271                                                         args.id);
1272                if (ret)
1273                        goto error;
1274
1275                rscs[i].id = args.id;
1276        }
1277
1278        mutex_unlock(&apart->mlock);
1279
1280        if (copy_to_user((void __user *)args.rscs, rscs,
1281                         sizeof(*rscs) * args.num_rscs)) {
1282                kfree(rscs);
1283                return -EFAULT;
1284        }
1285
1286        /*
1287         * If it is required to broadcast to whole partition, it needs to
1288         * return the actual number of broadcast resources as some tiles
1289         * can be gated
1290         */
1291        if (args.flag & XAIE_BROADCAST_ALL) {
1292                struct aie_rsc_bc_req __user *uargs = user_args;
1293
1294                if (copy_to_user((void __user *)&uargs->num_rscs,
1295                                 &args.num_rscs, sizeof(args.num_rscs))) {
1296                        kfree(rscs);
1297                        return -EFAULT;
1298                }
1299        }
1300
1301        kfree(rscs);
1302        return 0;
1303error:
1304        mutex_unlock(&apart->mlock);
1305        kfree(rscs);
1306        return ret;
1307}
1308
1309/**
1310 * aie_part_rscmgr_set_static() - sets statically allocated resources bitmaps
1311 *
1312 * @apart: AI engine partition
1313 * @meta: meta data which contains the statically allocated resources bitmaps
1314 *
1315 * @return: 0 for success, negative value for failure
1316 *
1317 * This function takes the static bitmap information from meta data and fill
1318 * in the static bitmap.
1319 */
1320int aie_part_rscmgr_set_static(struct aie_partition *apart, void *meta)
1321{
1322        struct aie_rsc_meta_header *header = meta;
1323        struct aie_rsc_bitmap *bitmap;
1324        u64 i, num_bitmaps, offset;
1325
1326        if (!header) {
1327                dev_err(&apart->dev,
1328                        "failed to get static resources, meta data is NULL.\n");
1329                return -EINVAL;
1330        }
1331
1332        /*
1333         * For now, the stat field of the header only contains the number of
1334         * bitmaps.
1335         */
1336        num_bitmaps = header->stat;
1337        offset = header->bitmap_off;
1338        if (!num_bitmaps || offset < sizeof(*header)) {
1339                dev_err(&apart->dev,
1340                        "failed to get static resources, invalid header.\n");
1341                return -EINVAL;
1342        }
1343
1344        bitmap = (struct aie_rsc_bitmap *)(meta + offset);
1345        for (i = 0; i < num_bitmaps; i++) {
1346                struct aie_rsc_stat *rstat;
1347                const struct aie_mod_rsc_attr *mrattr;
1348                u64 header = bitmap->header;
1349                u32 lrlen, rlen, ttype, mtype, rtype, total;
1350
1351                ttype = AIE_RSC_BITMAP_HEAD_VAL(TILETYPE, header);
1352                mtype = AIE_RSC_BITMAP_HEAD_VAL(MODTYPE, header);
1353                rtype = AIE_RSC_BITMAP_HEAD_VAL(RSCTYPE, header);
1354                rlen = AIE_RSC_BITMAP_HEAD_VAL(LENU64, header);
1355
1356                if (!rlen) {
1357                        dev_err(&apart->dev,
1358                                "invalid static bitmap[%llu], length is 0.\n",
1359                                i);
1360                        return -EINVAL;
1361                }
1362
1363                mrattr = aie_dev_get_mod_rsc_attr(apart->adev, ttype, mtype,
1364                                                  rtype);
1365                if (!mrattr) {
1366                        dev_err(&apart->dev,
1367                                "invalid static bitmap[%llu], invalid tile(%u)/module(%u)/rsce(%u) types combination.\n",
1368                                i, ttype, mtype, rtype);
1369                        return -EINVAL;
1370                }
1371
1372                total = mrattr->num_rscs * apart->range.size.col *
1373                        aie_part_get_tile_rows(apart, ttype);
1374                lrlen = BITS_TO_LONGS(total);
1375                if (rlen != lrlen) {
1376                        dev_err(&apart->dev,
1377                                "invalid static bitmap[%llu], tile(%u)/module(%u)/rscs(%u), expect len(%u), actual(%u).\n",
1378                                i, ttype, mtype, rtype, lrlen, rlen);
1379                        return -EINVAL;
1380                }
1381
1382                rstat = aie_part_get_ttype_rsc_bitmaps(apart, ttype, mtype,
1383                                                       rtype);
1384                /* if bitmap length is not 0, bitmap pointer cannot be NULL. */
1385                if (WARN_ON(!rstat || !rstat->sbits.bitmap))
1386                        return -EFAULT;
1387
1388                /* copy the bitmap from meta data */
1389                bitmap_copy(rstat->sbits.bitmap,
1390                            (unsigned long *)bitmap->bitmap, total);
1391
1392                bitmap = (struct aie_rsc_bitmap *)((void *)bitmap +
1393                                                   sizeof(header) +
1394                                                   rlen * sizeof(u64));
1395        }
1396
1397        return 0;
1398}
1399
1400/**
1401 * aie_part_rscmgr_check_static() - check the number of static resources
1402 *
1403 * @rstat: resource statistics structure which contains bitmaps of a resource
1404 *         type of a module type of a tile type.
1405 * @sbit: start bit of the resource bitmap of a tile of a module
1406 * @total: number of total resources bits to check
1407 *
1408 * @return: number of static resources
1409 *
1410 * This function returns the number of static resources of a resource
1411 * bitmap.
1412 */
1413static int aie_part_rscmgr_check_static(struct aie_rsc_stat *rstat,
1414                                        u32 sbit, u32 total)
1415{
1416        u32 i;
1417        int num_static = 0;
1418
1419        for (i = sbit; i < sbit + total; i++) {
1420                if (aie_resource_testbit(&rstat->sbits, i))
1421                        num_static++;
1422        }
1423
1424        return num_static;
1425}
1426
1427/**
1428 * aie_part_rscmgr_check_avail() - check the number of available resources
1429 *
1430 * @rstat: resource statistics structure which contains bitmaps of a resource
1431 *         type of a module type of a tile type.
1432 * @sbit: start bit of the resource bitmap of a tile of a module
1433 * @total: number of total resources bits to check
1434 *
1435 * @return: number of available resources for success, negative value for
1436 *          failure
1437 *
1438 * This function returns the number of available resources of a resource
1439 * bitmap.
1440 */
1441static int aie_part_rscmgr_check_avail(struct aie_rsc_stat *rstat,
1442                                       u32 sbit, u32 total)
1443{
1444        return aie_resource_check_common_avail(&rstat->rbits,
1445                                               &rstat->sbits,
1446                                               sbit, total);
1447}
1448
1449/**
1450 * aie_part_rscmgr_get_statistics() - get resource statistics based on user
1451 *                                    request
1452 *
1453 * @apart: AI engine partition
1454 * @user_args: user resource statistics request. it contains the number of
1455 *             resource statistics wants to get followed by the statistics
1456 *             array and the statistics type to specify if it is for static
1457 *             allocated resources or available resources. Each statistics
1458 *             element contains the tile location, module type and the resource
1459 *             type.
1460 *
1461 * @return: 0 for success, negative value for failure
1462 *
1463 * This function returns the resource statistics based on the user request.
1464 * If user requests for available resource statistics, it returns the number
1465 * of available resources of each resource statistics entry. If user requests
1466 * for static resources statistics, it returns the number of static resources
1467 * of each resource statistics entry.
1468 */
1469long aie_part_rscmgr_get_statistics(struct aie_partition *apart,
1470                                    void __user *user_args)
1471{
1472        struct aie_rsc_user_stat_array args;
1473        struct aie_rsc_user_stat __user *ustat_ptr;
1474        u32 i;
1475
1476        if (copy_from_user(&args, user_args, sizeof(args)))
1477                return -EFAULT;
1478
1479        if (args.stats_type >= AIE_RSC_STAT_TYPE_MAX) {
1480                dev_err(&apart->dev,
1481                        "get rsc statistics failed, invalid rsc stat type %u.\n",
1482                        args.stats_type);
1483                return -EINVAL;
1484        }
1485
1486        ustat_ptr = (struct aie_rsc_user_stat __user *)args.stats;
1487        for (i = 0; i < args.num_stats; i++) {
1488                struct aie_rsc_user_stat ustat;
1489                struct aie_rsc_stat *rstat;
1490                struct aie_location rloc, loc;
1491                long ret;
1492                int max_rscs, start_bit;
1493
1494                if (copy_from_user(&ustat, (void __user *)ustat_ptr,
1495                                   sizeof(ustat)))
1496                        return -EFAULT;
1497
1498                /* convert user tile loc to kernel tile loc format */
1499                rloc.col = (u32)(ustat.loc.col & 0xFF);
1500                rloc.row = (u32)(ustat.loc.row & 0xFF);
1501                ret = aie_part_adjust_loc(apart, rloc, &loc);
1502                if (ret < 0)
1503                        return ret;
1504
1505                if (ustat.type > AIE_RSCTYPE_MAX) {
1506                        dev_err(&apart->dev,
1507                                "get rsc statistics failed, invalid resource type %d.\n",
1508                                ustat.type);
1509                        return -EINVAL;
1510                }
1511
1512                rstat = aie_part_get_rsc_bitmaps(apart, loc, ustat.mod,
1513                                                 ustat.type);
1514                start_bit = aie_part_get_rsc_startbit(apart, loc, ustat.mod,
1515                                                      ustat.type);
1516                if (!rstat || start_bit < 0) {
1517                        dev_err(&apart->dev,
1518                                "get rsc statistics failed, invalid resource(%u,%u),mod:%u,rsc:%u.\n",
1519                                loc.col, loc.row, ustat.mod, ustat.type);
1520                        return -EINVAL;
1521                }
1522
1523                max_rscs = aie_part_get_mod_num_rscs(apart, loc, ustat.mod,
1524                                                     ustat.type);
1525                ret = mutex_lock_interruptible(&apart->mlock);
1526                if (ret)
1527                        return ret;
1528
1529                if (args.stats_type == AIE_RSC_STAT_TYPE_STATIC)
1530                        ustat.num_rscs = aie_part_rscmgr_check_static(rstat,
1531                                                                      start_bit,
1532                                                                      max_rscs);
1533                else
1534                        ustat.num_rscs = aie_part_rscmgr_check_avail(rstat,
1535                                                                     start_bit,
1536                                                                     max_rscs);
1537
1538                mutex_unlock(&apart->mlock);
1539                if (WARN_ON(ustat.num_rscs < 0))
1540                        return -EFAULT;
1541
1542                /* copy the information back to userspace */
1543                if (copy_to_user((void __user *)ustat_ptr, &ustat,
1544                                 sizeof(ustat)))
1545                        return -EFAULT;
1546
1547                ustat_ptr++;
1548        }
1549
1550        return 0;
1551}
1552