root/drivers/bus/fsl-mc/fsl-mc-allocator.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fsl_mc_is_allocatable
  2. fsl_mc_resource_pool_add_device
  3. fsl_mc_resource_pool_remove_device
  4. object_type_to_pool_type
  5. fsl_mc_resource_allocate
  6. fsl_mc_resource_free
  7. fsl_mc_object_allocate
  8. fsl_mc_object_free
  9. fsl_mc_populate_irq_pool
  10. fsl_mc_cleanup_irq_pool
  11. fsl_mc_allocate_irqs
  12. fsl_mc_free_irqs
  13. fsl_mc_init_all_resource_pools
  14. fsl_mc_cleanup_resource_pool
  15. fsl_mc_cleanup_all_resource_pools
  16. fsl_mc_allocator_probe
  17. fsl_mc_allocator_remove
  18. fsl_mc_allocator_driver_init
  19. fsl_mc_allocator_driver_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * fsl-mc object allocator driver
   4  *
   5  * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
   6  *
   7  */
   8 
   9 #include <linux/module.h>
  10 #include <linux/msi.h>
  11 #include <linux/fsl/mc.h>
  12 
  13 #include "fsl-mc-private.h"
  14 
  15 static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev)
  16 {
  17         return is_fsl_mc_bus_dpbp(mc_dev) ||
  18                is_fsl_mc_bus_dpmcp(mc_dev) ||
  19                is_fsl_mc_bus_dpcon(mc_dev);
  20 }
  21 
  22 /**
  23  * fsl_mc_resource_pool_add_device - add allocatable object to a resource
  24  * pool of a given fsl-mc bus
  25  *
  26  * @mc_bus: pointer to the fsl-mc bus
  27  * @pool_type: pool type
  28  * @mc_dev: pointer to allocatable fsl-mc device
  29  */
  30 static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
  31                                                                 *mc_bus,
  32                                                         enum fsl_mc_pool_type
  33                                                                 pool_type,
  34                                                         struct fsl_mc_device
  35                                                                 *mc_dev)
  36 {
  37         struct fsl_mc_resource_pool *res_pool;
  38         struct fsl_mc_resource *resource;
  39         struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
  40         int error = -EINVAL;
  41 
  42         if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
  43                 goto out;
  44         if (!fsl_mc_is_allocatable(mc_dev))
  45                 goto out;
  46         if (mc_dev->resource)
  47                 goto out;
  48 
  49         res_pool = &mc_bus->resource_pools[pool_type];
  50         if (res_pool->type != pool_type)
  51                 goto out;
  52         if (res_pool->mc_bus != mc_bus)
  53                 goto out;
  54 
  55         mutex_lock(&res_pool->mutex);
  56 
  57         if (res_pool->max_count < 0)
  58                 goto out_unlock;
  59         if (res_pool->free_count < 0 ||
  60             res_pool->free_count > res_pool->max_count)
  61                 goto out_unlock;
  62 
  63         resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
  64                                 GFP_KERNEL);
  65         if (!resource) {
  66                 error = -ENOMEM;
  67                 dev_err(&mc_bus_dev->dev,
  68                         "Failed to allocate memory for fsl_mc_resource\n");
  69                 goto out_unlock;
  70         }
  71 
  72         resource->type = pool_type;
  73         resource->id = mc_dev->obj_desc.id;
  74         resource->data = mc_dev;
  75         resource->parent_pool = res_pool;
  76         INIT_LIST_HEAD(&resource->node);
  77         list_add_tail(&resource->node, &res_pool->free_list);
  78         mc_dev->resource = resource;
  79         res_pool->free_count++;
  80         res_pool->max_count++;
  81         error = 0;
  82 out_unlock:
  83         mutex_unlock(&res_pool->mutex);
  84 out:
  85         return error;
  86 }
  87 
  88 /**
  89  * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
  90  * resource pool
  91  *
  92  * @mc_dev: pointer to allocatable fsl-mc device
  93  *
  94  * It permanently removes an allocatable fsl-mc device from the resource
  95  * pool. It's an error if the device is in use.
  96  */
  97 static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
  98                                                                    *mc_dev)
  99 {
 100         struct fsl_mc_device *mc_bus_dev;
 101         struct fsl_mc_bus *mc_bus;
 102         struct fsl_mc_resource_pool *res_pool;
 103         struct fsl_mc_resource *resource;
 104         int error = -EINVAL;
 105 
 106         if (!fsl_mc_is_allocatable(mc_dev))
 107                 goto out;
 108 
 109         resource = mc_dev->resource;
 110         if (!resource || resource->data != mc_dev)
 111                 goto out;
 112 
 113         mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
 114         mc_bus = to_fsl_mc_bus(mc_bus_dev);
 115         res_pool = resource->parent_pool;
 116         if (res_pool != &mc_bus->resource_pools[resource->type])
 117                 goto out;
 118 
 119         mutex_lock(&res_pool->mutex);
 120 
 121         if (res_pool->max_count <= 0)
 122                 goto out_unlock;
 123         if (res_pool->free_count <= 0 ||
 124             res_pool->free_count > res_pool->max_count)
 125                 goto out_unlock;
 126 
 127         /*
 128          * If the device is currently allocated, its resource is not
 129          * in the free list and thus, the device cannot be removed.
 130          */
 131         if (list_empty(&resource->node)) {
 132                 error = -EBUSY;
 133                 dev_err(&mc_bus_dev->dev,
 134                         "Device %s cannot be removed from resource pool\n",
 135                         dev_name(&mc_dev->dev));
 136                 goto out_unlock;
 137         }
 138 
 139         list_del_init(&resource->node);
 140         res_pool->free_count--;
 141         res_pool->max_count--;
 142 
 143         devm_kfree(&mc_bus_dev->dev, resource);
 144         mc_dev->resource = NULL;
 145         error = 0;
 146 out_unlock:
 147         mutex_unlock(&res_pool->mutex);
 148 out:
 149         return error;
 150 }
 151 
 152 static const char *const fsl_mc_pool_type_strings[] = {
 153         [FSL_MC_POOL_DPMCP] = "dpmcp",
 154         [FSL_MC_POOL_DPBP] = "dpbp",
 155         [FSL_MC_POOL_DPCON] = "dpcon",
 156         [FSL_MC_POOL_IRQ] = "irq",
 157 };
 158 
 159 static int __must_check object_type_to_pool_type(const char *object_type,
 160                                                  enum fsl_mc_pool_type
 161                                                                 *pool_type)
 162 {
 163         unsigned int i;
 164 
 165         for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
 166                 if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
 167                         *pool_type = i;
 168                         return 0;
 169                 }
 170         }
 171 
 172         return -EINVAL;
 173 }
 174 
 175 int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
 176                                           enum fsl_mc_pool_type pool_type,
 177                                           struct fsl_mc_resource **new_resource)
 178 {
 179         struct fsl_mc_resource_pool *res_pool;
 180         struct fsl_mc_resource *resource;
 181         struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
 182         int error = -EINVAL;
 183 
 184         BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
 185                      FSL_MC_NUM_POOL_TYPES);
 186 
 187         *new_resource = NULL;
 188         if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
 189                 goto out;
 190 
 191         res_pool = &mc_bus->resource_pools[pool_type];
 192         if (res_pool->mc_bus != mc_bus)
 193                 goto out;
 194 
 195         mutex_lock(&res_pool->mutex);
 196         resource = list_first_entry_or_null(&res_pool->free_list,
 197                                             struct fsl_mc_resource, node);
 198 
 199         if (!resource) {
 200                 error = -ENXIO;
 201                 dev_err(&mc_bus_dev->dev,
 202                         "No more resources of type %s left\n",
 203                         fsl_mc_pool_type_strings[pool_type]);
 204                 goto out_unlock;
 205         }
 206 
 207         if (resource->type != pool_type)
 208                 goto out_unlock;
 209         if (resource->parent_pool != res_pool)
 210                 goto out_unlock;
 211         if (res_pool->free_count <= 0 ||
 212             res_pool->free_count > res_pool->max_count)
 213                 goto out_unlock;
 214 
 215         list_del_init(&resource->node);
 216 
 217         res_pool->free_count--;
 218         error = 0;
 219 out_unlock:
 220         mutex_unlock(&res_pool->mutex);
 221         *new_resource = resource;
 222 out:
 223         return error;
 224 }
 225 EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
 226 
 227 void fsl_mc_resource_free(struct fsl_mc_resource *resource)
 228 {
 229         struct fsl_mc_resource_pool *res_pool;
 230 
 231         res_pool = resource->parent_pool;
 232         if (resource->type != res_pool->type)
 233                 return;
 234 
 235         mutex_lock(&res_pool->mutex);
 236         if (res_pool->free_count < 0 ||
 237             res_pool->free_count >= res_pool->max_count)
 238                 goto out_unlock;
 239 
 240         if (!list_empty(&resource->node))
 241                 goto out_unlock;
 242 
 243         list_add_tail(&resource->node, &res_pool->free_list);
 244         res_pool->free_count++;
 245 out_unlock:
 246         mutex_unlock(&res_pool->mutex);
 247 }
 248 EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
 249 
 250 /**
 251  * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
 252  * pool type from a given fsl-mc bus instance
 253  *
 254  * @mc_dev: fsl-mc device which is used in conjunction with the
 255  * allocated object
 256  * @pool_type: pool type
 257  * @new_mc_dev: pointer to area where the pointer to the allocated device
 258  * is to be returned
 259  *
 260  * Allocatable objects are always used in conjunction with some functional
 261  * device.  This function allocates an object of the specified type from
 262  * the DPRC containing the functional device.
 263  *
 264  * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
 265  * portals are allocated using fsl_mc_portal_allocate(), instead of
 266  * this function.
 267  */
 268 int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
 269                                         enum fsl_mc_pool_type pool_type,
 270                                         struct fsl_mc_device **new_mc_adev)
 271 {
 272         struct fsl_mc_device *mc_bus_dev;
 273         struct fsl_mc_bus *mc_bus;
 274         struct fsl_mc_device *mc_adev;
 275         int error = -EINVAL;
 276         struct fsl_mc_resource *resource = NULL;
 277 
 278         *new_mc_adev = NULL;
 279         if (mc_dev->flags & FSL_MC_IS_DPRC)
 280                 goto error;
 281 
 282         if (!dev_is_fsl_mc(mc_dev->dev.parent))
 283                 goto error;
 284 
 285         if (pool_type == FSL_MC_POOL_DPMCP)
 286                 goto error;
 287 
 288         mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
 289         mc_bus = to_fsl_mc_bus(mc_bus_dev);
 290         error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
 291         if (error < 0)
 292                 goto error;
 293 
 294         mc_adev = resource->data;
 295         if (!mc_adev)
 296                 goto error;
 297 
 298         mc_adev->consumer_link = device_link_add(&mc_dev->dev,
 299                                                  &mc_adev->dev,
 300                                                  DL_FLAG_AUTOREMOVE_CONSUMER);
 301         if (!mc_adev->consumer_link) {
 302                 error = -EINVAL;
 303                 goto error;
 304         }
 305 
 306         *new_mc_adev = mc_adev;
 307         return 0;
 308 error:
 309         if (resource)
 310                 fsl_mc_resource_free(resource);
 311 
 312         return error;
 313 }
 314 EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
 315 
 316 /**
 317  * fsl_mc_object_free - Returns an fsl-mc object to the resource
 318  * pool where it came from.
 319  * @mc_adev: Pointer to the fsl-mc device
 320  */
 321 void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
 322 {
 323         struct fsl_mc_resource *resource;
 324 
 325         resource = mc_adev->resource;
 326         if (resource->type == FSL_MC_POOL_DPMCP)
 327                 return;
 328         if (resource->data != mc_adev)
 329                 return;
 330 
 331         fsl_mc_resource_free(resource);
 332 
 333         mc_adev->consumer_link = NULL;
 334 }
 335 EXPORT_SYMBOL_GPL(fsl_mc_object_free);
 336 
 337 /*
 338  * A DPRC and the devices in the DPRC all share the same GIC-ITS device
 339  * ID.  A block of IRQs is pre-allocated and maintained in a pool
 340  * from which devices can allocate them when needed.
 341  */
 342 
 343 /*
 344  * Initialize the interrupt pool associated with an fsl-mc bus.
 345  * It allocates a block of IRQs from the GIC-ITS.
 346  */
 347 int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
 348                              unsigned int irq_count)
 349 {
 350         unsigned int i;
 351         struct msi_desc *msi_desc;
 352         struct fsl_mc_device_irq *irq_resources;
 353         struct fsl_mc_device_irq *mc_dev_irq;
 354         int error;
 355         struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
 356         struct fsl_mc_resource_pool *res_pool =
 357                         &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
 358 
 359         if (irq_count == 0 ||
 360             irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)
 361                 return -EINVAL;
 362 
 363         error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
 364         if (error < 0)
 365                 return error;
 366 
 367         irq_resources = devm_kcalloc(&mc_bus_dev->dev,
 368                                      irq_count, sizeof(*irq_resources),
 369                                      GFP_KERNEL);
 370         if (!irq_resources) {
 371                 error = -ENOMEM;
 372                 goto cleanup_msi_irqs;
 373         }
 374 
 375         for (i = 0; i < irq_count; i++) {
 376                 mc_dev_irq = &irq_resources[i];
 377 
 378                 /*
 379                  * NOTE: This mc_dev_irq's MSI addr/value pair will be set
 380                  * by the fsl_mc_msi_write_msg() callback
 381                  */
 382                 mc_dev_irq->resource.type = res_pool->type;
 383                 mc_dev_irq->resource.data = mc_dev_irq;
 384                 mc_dev_irq->resource.parent_pool = res_pool;
 385                 INIT_LIST_HEAD(&mc_dev_irq->resource.node);
 386                 list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
 387         }
 388 
 389         for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
 390                 mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
 391                 mc_dev_irq->msi_desc = msi_desc;
 392                 mc_dev_irq->resource.id = msi_desc->irq;
 393         }
 394 
 395         res_pool->max_count = irq_count;
 396         res_pool->free_count = irq_count;
 397         mc_bus->irq_resources = irq_resources;
 398         return 0;
 399 
 400 cleanup_msi_irqs:
 401         fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
 402         return error;
 403 }
 404 EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
 405 
 406 /**
 407  * Teardown the interrupt pool associated with an fsl-mc bus.
 408  * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
 409  */
 410 void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
 411 {
 412         struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
 413         struct fsl_mc_resource_pool *res_pool =
 414                         &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
 415 
 416         if (!mc_bus->irq_resources)
 417                 return;
 418 
 419         if (res_pool->max_count == 0)
 420                 return;
 421 
 422         if (res_pool->free_count != res_pool->max_count)
 423                 return;
 424 
 425         INIT_LIST_HEAD(&res_pool->free_list);
 426         res_pool->max_count = 0;
 427         res_pool->free_count = 0;
 428         mc_bus->irq_resources = NULL;
 429         fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
 430 }
 431 EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
 432 
 433 /**
 434  * Allocate the IRQs required by a given fsl-mc device.
 435  */
 436 int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
 437 {
 438         int i;
 439         int irq_count;
 440         int res_allocated_count = 0;
 441         int error = -EINVAL;
 442         struct fsl_mc_device_irq **irqs = NULL;
 443         struct fsl_mc_bus *mc_bus;
 444         struct fsl_mc_resource_pool *res_pool;
 445 
 446         if (mc_dev->irqs)
 447                 return -EINVAL;
 448 
 449         irq_count = mc_dev->obj_desc.irq_count;
 450         if (irq_count == 0)
 451                 return -EINVAL;
 452 
 453         if (is_fsl_mc_bus_dprc(mc_dev))
 454                 mc_bus = to_fsl_mc_bus(mc_dev);
 455         else
 456                 mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
 457 
 458         if (!mc_bus->irq_resources)
 459                 return -EINVAL;
 460 
 461         res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
 462         if (res_pool->free_count < irq_count) {
 463                 dev_err(&mc_dev->dev,
 464                         "Not able to allocate %u irqs for device\n", irq_count);
 465                 return -ENOSPC;
 466         }
 467 
 468         irqs = devm_kcalloc(&mc_dev->dev, irq_count, sizeof(irqs[0]),
 469                             GFP_KERNEL);
 470         if (!irqs)
 471                 return -ENOMEM;
 472 
 473         for (i = 0; i < irq_count; i++) {
 474                 struct fsl_mc_resource *resource;
 475 
 476                 error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
 477                                                  &resource);
 478                 if (error < 0)
 479                         goto error_resource_alloc;
 480 
 481                 irqs[i] = to_fsl_mc_irq(resource);
 482                 res_allocated_count++;
 483 
 484                 irqs[i]->mc_dev = mc_dev;
 485                 irqs[i]->dev_irq_index = i;
 486         }
 487 
 488         mc_dev->irqs = irqs;
 489         return 0;
 490 
 491 error_resource_alloc:
 492         for (i = 0; i < res_allocated_count; i++) {
 493                 irqs[i]->mc_dev = NULL;
 494                 fsl_mc_resource_free(&irqs[i]->resource);
 495         }
 496 
 497         return error;
 498 }
 499 EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
 500 
 501 /*
 502  * Frees the IRQs that were allocated for an fsl-mc device.
 503  */
 504 void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
 505 {
 506         int i;
 507         int irq_count;
 508         struct fsl_mc_bus *mc_bus;
 509         struct fsl_mc_device_irq **irqs = mc_dev->irqs;
 510 
 511         if (!irqs)
 512                 return;
 513 
 514         irq_count = mc_dev->obj_desc.irq_count;
 515 
 516         if (is_fsl_mc_bus_dprc(mc_dev))
 517                 mc_bus = to_fsl_mc_bus(mc_dev);
 518         else
 519                 mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
 520 
 521         if (!mc_bus->irq_resources)
 522                 return;
 523 
 524         for (i = 0; i < irq_count; i++) {
 525                 irqs[i]->mc_dev = NULL;
 526                 fsl_mc_resource_free(&irqs[i]->resource);
 527         }
 528 
 529         mc_dev->irqs = NULL;
 530 }
 531 EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
 532 
 533 void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
 534 {
 535         int pool_type;
 536         struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
 537 
 538         for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
 539                 struct fsl_mc_resource_pool *res_pool =
 540                     &mc_bus->resource_pools[pool_type];
 541 
 542                 res_pool->type = pool_type;
 543                 res_pool->max_count = 0;
 544                 res_pool->free_count = 0;
 545                 res_pool->mc_bus = mc_bus;
 546                 INIT_LIST_HEAD(&res_pool->free_list);
 547                 mutex_init(&res_pool->mutex);
 548         }
 549 }
 550 
 551 static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
 552                                          enum fsl_mc_pool_type pool_type)
 553 {
 554         struct fsl_mc_resource *resource;
 555         struct fsl_mc_resource *next;
 556         struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
 557         struct fsl_mc_resource_pool *res_pool =
 558                                         &mc_bus->resource_pools[pool_type];
 559         int free_count = 0;
 560 
 561         list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
 562                 free_count++;
 563                 devm_kfree(&mc_bus_dev->dev, resource);
 564         }
 565 }
 566 
 567 void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
 568 {
 569         int pool_type;
 570 
 571         for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
 572                 fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
 573 }
 574 
 575 /**
 576  * fsl_mc_allocator_probe - callback invoked when an allocatable device is
 577  * being added to the system
 578  */
 579 static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
 580 {
 581         enum fsl_mc_pool_type pool_type;
 582         struct fsl_mc_device *mc_bus_dev;
 583         struct fsl_mc_bus *mc_bus;
 584         int error;
 585 
 586         if (!fsl_mc_is_allocatable(mc_dev))
 587                 return -EINVAL;
 588 
 589         mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
 590         if (!dev_is_fsl_mc(&mc_bus_dev->dev))
 591                 return -EINVAL;
 592 
 593         mc_bus = to_fsl_mc_bus(mc_bus_dev);
 594         error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
 595         if (error < 0)
 596                 return error;
 597 
 598         error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
 599         if (error < 0)
 600                 return error;
 601 
 602         dev_dbg(&mc_dev->dev,
 603                 "Allocatable fsl-mc device bound to fsl_mc_allocator driver");
 604         return 0;
 605 }
 606 
 607 /**
 608  * fsl_mc_allocator_remove - callback invoked when an allocatable device is
 609  * being removed from the system
 610  */
 611 static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
 612 {
 613         int error;
 614 
 615         if (!fsl_mc_is_allocatable(mc_dev))
 616                 return -EINVAL;
 617 
 618         if (mc_dev->resource) {
 619                 error = fsl_mc_resource_pool_remove_device(mc_dev);
 620                 if (error < 0)
 621                         return error;
 622         }
 623 
 624         dev_dbg(&mc_dev->dev,
 625                 "Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
 626         return 0;
 627 }
 628 
 629 static const struct fsl_mc_device_id match_id_table[] = {
 630         {
 631          .vendor = FSL_MC_VENDOR_FREESCALE,
 632          .obj_type = "dpbp",
 633         },
 634         {
 635          .vendor = FSL_MC_VENDOR_FREESCALE,
 636          .obj_type = "dpmcp",
 637         },
 638         {
 639          .vendor = FSL_MC_VENDOR_FREESCALE,
 640          .obj_type = "dpcon",
 641         },
 642         {.vendor = 0x0},
 643 };
 644 
 645 static struct fsl_mc_driver fsl_mc_allocator_driver = {
 646         .driver = {
 647                    .name = "fsl_mc_allocator",
 648                    .pm = NULL,
 649                    },
 650         .match_id_table = match_id_table,
 651         .probe = fsl_mc_allocator_probe,
 652         .remove = fsl_mc_allocator_remove,
 653 };
 654 
 655 int __init fsl_mc_allocator_driver_init(void)
 656 {
 657         return fsl_mc_driver_register(&fsl_mc_allocator_driver);
 658 }
 659 
 660 void fsl_mc_allocator_driver_exit(void)
 661 {
 662         fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
 663 }

/* [<][>][^][v][top][bottom][index][help] */