3
0
mirror of https://github.com/Qortal/Brooklyn.git synced 2025-02-22 15:15:53 +00:00
Brooklyn/drivers/bus/fsl-mc/fsl-mc-allocator.c
Raziel K. Crowe 04c1822c0a There is a moose on the mool buff
Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey! Ring the door. Take your seat moosey!
2022-03-15 21:13:23 +05:00

670 lines
16 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* fsl-mc object allocator driver
*
* Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
*
*/
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/fsl/mc.h>
#include "fsl-mc-private.h"
static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev)
{
return is_fsl_mc_bus_dpbp(mc_dev) ||
is_fsl_mc_bus_dpmcp(mc_dev) ||
is_fsl_mc_bus_dpcon(mc_dev);
}
/**
* fsl_mc_resource_pool_add_device - add allocatable object to a resource
* pool of a given fsl-mc bus
*
* @mc_bus: pointer to the fsl-mc bus
* @pool_type: pool type
* @mc_dev: pointer to allocatable fsl-mc device
*/
static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
*mc_bus,
enum fsl_mc_pool_type
pool_type,
struct fsl_mc_device
*mc_dev)
{
struct fsl_mc_resource_pool *res_pool;
struct fsl_mc_resource *resource;
struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
int error = -EINVAL;
if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
goto out;
if (!fsl_mc_is_allocatable(mc_dev))
goto out;
if (mc_dev->resource)
goto out;
res_pool = &mc_bus->resource_pools[pool_type];
if (res_pool->type != pool_type)
goto out;
if (res_pool->mc_bus != mc_bus)
goto out;
mutex_lock(&res_pool->mutex);
if (res_pool->max_count < 0)
goto out_unlock;
if (res_pool->free_count < 0 ||
res_pool->free_count > res_pool->max_count)
goto out_unlock;
resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
GFP_KERNEL);
if (!resource) {
error = -ENOMEM;
dev_err(&mc_bus_dev->dev,
"Failed to allocate memory for fsl_mc_resource\n");
goto out_unlock;
}
resource->type = pool_type;
resource->id = mc_dev->obj_desc.id;
resource->data = mc_dev;
resource->parent_pool = res_pool;
INIT_LIST_HEAD(&resource->node);
list_add_tail(&resource->node, &res_pool->free_list);
mc_dev->resource = resource;
res_pool->free_count++;
res_pool->max_count++;
error = 0;
out_unlock:
mutex_unlock(&res_pool->mutex);
out:
return error;
}
/**
* fsl_mc_resource_pool_remove_device - remove an allocatable device from a
* resource pool
*
* @mc_dev: pointer to allocatable fsl-mc device
*
* It permanently removes an allocatable fsl-mc device from the resource
* pool. It's an error if the device is in use.
*/
static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
*mc_dev)
{
struct fsl_mc_device *mc_bus_dev;
struct fsl_mc_bus *mc_bus;
struct fsl_mc_resource_pool *res_pool;
struct fsl_mc_resource *resource;
int error = -EINVAL;
if (!fsl_mc_is_allocatable(mc_dev))
goto out;
resource = mc_dev->resource;
if (!resource || resource->data != mc_dev)
goto out;
mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
mc_bus = to_fsl_mc_bus(mc_bus_dev);
res_pool = resource->parent_pool;
if (res_pool != &mc_bus->resource_pools[resource->type])
goto out;
mutex_lock(&res_pool->mutex);
if (res_pool->max_count <= 0)
goto out_unlock;
if (res_pool->free_count <= 0 ||
res_pool->free_count > res_pool->max_count)
goto out_unlock;
/*
* If the device is currently allocated, its resource is not
* in the free list and thus, the device cannot be removed.
*/
if (list_empty(&resource->node)) {
error = -EBUSY;
dev_err(&mc_bus_dev->dev,
"Device %s cannot be removed from resource pool\n",
dev_name(&mc_dev->dev));
goto out_unlock;
}
list_del_init(&resource->node);
res_pool->free_count--;
res_pool->max_count--;
devm_kfree(&mc_bus_dev->dev, resource);
mc_dev->resource = NULL;
error = 0;
out_unlock:
mutex_unlock(&res_pool->mutex);
out:
return error;
}
static const char *const fsl_mc_pool_type_strings[] = {
[FSL_MC_POOL_DPMCP] = "dpmcp",
[FSL_MC_POOL_DPBP] = "dpbp",
[FSL_MC_POOL_DPCON] = "dpcon",
[FSL_MC_POOL_IRQ] = "irq",
};
static int __must_check object_type_to_pool_type(const char *object_type,
enum fsl_mc_pool_type
*pool_type)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
*pool_type = i;
return 0;
}
}
return -EINVAL;
}
int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
enum fsl_mc_pool_type pool_type,
struct fsl_mc_resource **new_resource)
{
struct fsl_mc_resource_pool *res_pool;
struct fsl_mc_resource *resource;
struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
int error = -EINVAL;
BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
FSL_MC_NUM_POOL_TYPES);
*new_resource = NULL;
if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
goto out;
res_pool = &mc_bus->resource_pools[pool_type];
if (res_pool->mc_bus != mc_bus)
goto out;
mutex_lock(&res_pool->mutex);
resource = list_first_entry_or_null(&res_pool->free_list,
struct fsl_mc_resource, node);
if (!resource) {
error = -ENXIO;
dev_err(&mc_bus_dev->dev,
"No more resources of type %s left\n",
fsl_mc_pool_type_strings[pool_type]);
goto out_unlock;
}
if (resource->type != pool_type)
goto out_unlock;
if (resource->parent_pool != res_pool)
goto out_unlock;
if (res_pool->free_count <= 0 ||
res_pool->free_count > res_pool->max_count)
goto out_unlock;
list_del_init(&resource->node);
res_pool->free_count--;
error = 0;
out_unlock:
mutex_unlock(&res_pool->mutex);
*new_resource = resource;
out:
return error;
}
EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
void fsl_mc_resource_free(struct fsl_mc_resource *resource)
{
struct fsl_mc_resource_pool *res_pool;
res_pool = resource->parent_pool;
if (resource->type != res_pool->type)
return;
mutex_lock(&res_pool->mutex);
if (res_pool->free_count < 0 ||
res_pool->free_count >= res_pool->max_count)
goto out_unlock;
if (!list_empty(&resource->node))
goto out_unlock;
list_add_tail(&resource->node, &res_pool->free_list);
res_pool->free_count++;
out_unlock:
mutex_unlock(&res_pool->mutex);
}
EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
/**
* fsl_mc_object_allocate - Allocates an fsl-mc object of the given
* pool type from a given fsl-mc bus instance
*
* @mc_dev: fsl-mc device which is used in conjunction with the
* allocated object
* @pool_type: pool type
* @new_mc_adev: pointer to area where the pointer to the allocated device
* is to be returned
*
* Allocatable objects are always used in conjunction with some functional
* device. This function allocates an object of the specified type from
* the DPRC containing the functional device.
*
* NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
* portals are allocated using fsl_mc_portal_allocate(), instead of
* this function.
*/
int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
enum fsl_mc_pool_type pool_type,
struct fsl_mc_device **new_mc_adev)
{
struct fsl_mc_device *mc_bus_dev;
struct fsl_mc_bus *mc_bus;
struct fsl_mc_device *mc_adev;
int error = -EINVAL;
struct fsl_mc_resource *resource = NULL;
*new_mc_adev = NULL;
if (mc_dev->flags & FSL_MC_IS_DPRC)
goto error;
if (!dev_is_fsl_mc(mc_dev->dev.parent))
goto error;
if (pool_type == FSL_MC_POOL_DPMCP)
goto error;
mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
mc_bus = to_fsl_mc_bus(mc_bus_dev);
error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
if (error < 0)
goto error;
mc_adev = resource->data;
if (!mc_adev) {
error = -EINVAL;
goto error;
}
mc_adev->consumer_link = device_link_add(&mc_dev->dev,
&mc_adev->dev,
DL_FLAG_AUTOREMOVE_CONSUMER);
if (!mc_adev->consumer_link) {
error = -EINVAL;
goto error;
}
*new_mc_adev = mc_adev;
return 0;
error:
if (resource)
fsl_mc_resource_free(resource);
return error;
}
EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
/**
* fsl_mc_object_free - Returns an fsl-mc object to the resource
* pool where it came from.
* @mc_adev: Pointer to the fsl-mc device
*/
void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
{
struct fsl_mc_resource *resource;
resource = mc_adev->resource;
if (resource->type == FSL_MC_POOL_DPMCP)
return;
if (resource->data != mc_adev)
return;
fsl_mc_resource_free(resource);
mc_adev->consumer_link = NULL;
}
EXPORT_SYMBOL_GPL(fsl_mc_object_free);
/*
* A DPRC and the devices in the DPRC all share the same GIC-ITS device
* ID. A block of IRQs is pre-allocated and maintained in a pool
* from which devices can allocate them when needed.
*/
/*
* Initialize the interrupt pool associated with an fsl-mc bus.
* It allocates a block of IRQs from the GIC-ITS.
*/
int fsl_mc_populate_irq_pool(struct fsl_mc_device *mc_bus_dev,
unsigned int irq_count)
{
unsigned int i;
struct msi_desc *msi_desc;
struct fsl_mc_device_irq *irq_resources;
struct fsl_mc_device_irq *mc_dev_irq;
int error;
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
struct fsl_mc_resource_pool *res_pool =
&mc_bus->resource_pools[FSL_MC_POOL_IRQ];
/* do nothing if the IRQ pool is already populated */
if (mc_bus->irq_resources)
return 0;
if (irq_count == 0 ||
irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)
return -EINVAL;
error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
if (error < 0)
return error;
irq_resources = devm_kcalloc(&mc_bus_dev->dev,
irq_count, sizeof(*irq_resources),
GFP_KERNEL);
if (!irq_resources) {
error = -ENOMEM;
goto cleanup_msi_irqs;
}
for (i = 0; i < irq_count; i++) {
mc_dev_irq = &irq_resources[i];
/*
* NOTE: This mc_dev_irq's MSI addr/value pair will be set
* by the fsl_mc_msi_write_msg() callback
*/
mc_dev_irq->resource.type = res_pool->type;
mc_dev_irq->resource.data = mc_dev_irq;
mc_dev_irq->resource.parent_pool = res_pool;
INIT_LIST_HEAD(&mc_dev_irq->resource.node);
list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
}
for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
mc_dev_irq->msi_desc = msi_desc;
mc_dev_irq->resource.id = msi_desc->irq;
}
res_pool->max_count = irq_count;
res_pool->free_count = irq_count;
mc_bus->irq_resources = irq_resources;
return 0;
cleanup_msi_irqs:
fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
return error;
}
EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
/*
* Teardown the interrupt pool associated with an fsl-mc bus.
* It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
*/
void fsl_mc_cleanup_irq_pool(struct fsl_mc_device *mc_bus_dev)
{
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
struct fsl_mc_resource_pool *res_pool =
&mc_bus->resource_pools[FSL_MC_POOL_IRQ];
if (!mc_bus->irq_resources)
return;
if (res_pool->max_count == 0)
return;
if (res_pool->free_count != res_pool->max_count)
return;
INIT_LIST_HEAD(&res_pool->free_list);
res_pool->max_count = 0;
res_pool->free_count = 0;
mc_bus->irq_resources = NULL;
fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
}
EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
/*
* Allocate the IRQs required by a given fsl-mc device.
*/
int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
{
int i;
int irq_count;
int res_allocated_count = 0;
int error = -EINVAL;
struct fsl_mc_device_irq **irqs = NULL;
struct fsl_mc_bus *mc_bus;
struct fsl_mc_resource_pool *res_pool;
if (mc_dev->irqs)
return -EINVAL;
irq_count = mc_dev->obj_desc.irq_count;
if (irq_count == 0)
return -EINVAL;
if (is_fsl_mc_bus_dprc(mc_dev))
mc_bus = to_fsl_mc_bus(mc_dev);
else
mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
if (!mc_bus->irq_resources)
return -EINVAL;
res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
if (res_pool->free_count < irq_count) {
dev_err(&mc_dev->dev,
"Not able to allocate %u irqs for device\n", irq_count);
return -ENOSPC;
}
irqs = devm_kcalloc(&mc_dev->dev, irq_count, sizeof(irqs[0]),
GFP_KERNEL);
if (!irqs)
return -ENOMEM;
for (i = 0; i < irq_count; i++) {
struct fsl_mc_resource *resource;
error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
&resource);
if (error < 0)
goto error_resource_alloc;
irqs[i] = to_fsl_mc_irq(resource);
res_allocated_count++;
irqs[i]->mc_dev = mc_dev;
irqs[i]->dev_irq_index = i;
}
mc_dev->irqs = irqs;
return 0;
error_resource_alloc:
for (i = 0; i < res_allocated_count; i++) {
irqs[i]->mc_dev = NULL;
fsl_mc_resource_free(&irqs[i]->resource);
}
return error;
}
EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
/*
* Frees the IRQs that were allocated for an fsl-mc device.
*/
void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
{
int i;
int irq_count;
struct fsl_mc_bus *mc_bus;
struct fsl_mc_device_irq **irqs = mc_dev->irqs;
if (!irqs)
return;
irq_count = mc_dev->obj_desc.irq_count;
if (is_fsl_mc_bus_dprc(mc_dev))
mc_bus = to_fsl_mc_bus(mc_dev);
else
mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
if (!mc_bus->irq_resources)
return;
for (i = 0; i < irq_count; i++) {
irqs[i]->mc_dev = NULL;
fsl_mc_resource_free(&irqs[i]->resource);
}
mc_dev->irqs = NULL;
}
EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
{
int pool_type;
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
struct fsl_mc_resource_pool *res_pool =
&mc_bus->resource_pools[pool_type];
res_pool->type = pool_type;
res_pool->max_count = 0;
res_pool->free_count = 0;
res_pool->mc_bus = mc_bus;
INIT_LIST_HEAD(&res_pool->free_list);
mutex_init(&res_pool->mutex);
}
}
static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
enum fsl_mc_pool_type pool_type)
{
struct fsl_mc_resource *resource;
struct fsl_mc_resource *next;
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
struct fsl_mc_resource_pool *res_pool =
&mc_bus->resource_pools[pool_type];
int free_count = 0;
list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
free_count++;
devm_kfree(&mc_bus_dev->dev, resource);
}
}
void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
{
int pool_type;
for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
}
/*
* fsl_mc_allocator_probe - callback invoked when an allocatable device is
* being added to the system
*/
static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
{
enum fsl_mc_pool_type pool_type;
struct fsl_mc_device *mc_bus_dev;
struct fsl_mc_bus *mc_bus;
int error;
if (!fsl_mc_is_allocatable(mc_dev))
return -EINVAL;
mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
if (!dev_is_fsl_mc(&mc_bus_dev->dev))
return -EINVAL;
mc_bus = to_fsl_mc_bus(mc_bus_dev);
error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
if (error < 0)
return error;
error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
if (error < 0)
return error;
dev_dbg(&mc_dev->dev,
"Allocatable fsl-mc device bound to fsl_mc_allocator driver");
return 0;
}
/*
* fsl_mc_allocator_remove - callback invoked when an allocatable device is
* being removed from the system
*/
static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
{
int error;
if (!fsl_mc_is_allocatable(mc_dev))
return -EINVAL;
if (mc_dev->resource) {
error = fsl_mc_resource_pool_remove_device(mc_dev);
if (error < 0)
return error;
}
dev_dbg(&mc_dev->dev,
"Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
return 0;
}
static const struct fsl_mc_device_id match_id_table[] = {
{
.vendor = FSL_MC_VENDOR_FREESCALE,
.obj_type = "dpbp",
},
{
.vendor = FSL_MC_VENDOR_FREESCALE,
.obj_type = "dpmcp",
},
{
.vendor = FSL_MC_VENDOR_FREESCALE,
.obj_type = "dpcon",
},
{.vendor = 0x0},
};
static struct fsl_mc_driver fsl_mc_allocator_driver = {
.driver = {
.name = "fsl_mc_allocator",
.pm = NULL,
},
.match_id_table = match_id_table,
.probe = fsl_mc_allocator_probe,
.remove = fsl_mc_allocator_remove,
};
int __init fsl_mc_allocator_driver_init(void)
{
return fsl_mc_driver_register(&fsl_mc_allocator_driver);
}
void fsl_mc_allocator_driver_exit(void)
{
fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
}