cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fsl-mc-allocator.c (16268B)


      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
     15static 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 */
     30static 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;
     82out_unlock:
     83	mutex_unlock(&res_pool->mutex);
     84out:
     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 */
     97static 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;
    146out_unlock:
    147	mutex_unlock(&res_pool->mutex);
    148out:
    149	return error;
    150}
    151
    152static 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
    159static 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
    175int __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;
    219out_unlock:
    220	mutex_unlock(&res_pool->mutex);
    221	*new_resource = resource;
    222out:
    223	return error;
    224}
    225EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
    226
    227void 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++;
    245out_unlock:
    246	mutex_unlock(&res_pool->mutex);
    247}
    248EXPORT_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_adev: 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 */
    268int __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		error = -EINVAL;
    297		goto error;
    298	}
    299
    300	mc_adev->consumer_link = device_link_add(&mc_dev->dev,
    301						 &mc_adev->dev,
    302						 DL_FLAG_AUTOREMOVE_CONSUMER);
    303	if (!mc_adev->consumer_link) {
    304		error = -EINVAL;
    305		goto error;
    306	}
    307
    308	*new_mc_adev = mc_adev;
    309	return 0;
    310error:
    311	if (resource)
    312		fsl_mc_resource_free(resource);
    313
    314	return error;
    315}
    316EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
    317
    318/**
    319 * fsl_mc_object_free - Returns an fsl-mc object to the resource
    320 * pool where it came from.
    321 * @mc_adev: Pointer to the fsl-mc device
    322 */
    323void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
    324{
    325	struct fsl_mc_resource *resource;
    326
    327	resource = mc_adev->resource;
    328	if (resource->type == FSL_MC_POOL_DPMCP)
    329		return;
    330	if (resource->data != mc_adev)
    331		return;
    332
    333	fsl_mc_resource_free(resource);
    334
    335	mc_adev->consumer_link = NULL;
    336}
    337EXPORT_SYMBOL_GPL(fsl_mc_object_free);
    338
    339/*
    340 * A DPRC and the devices in the DPRC all share the same GIC-ITS device
    341 * ID.  A block of IRQs is pre-allocated and maintained in a pool
    342 * from which devices can allocate them when needed.
    343 */
    344
    345/*
    346 * Initialize the interrupt pool associated with an fsl-mc bus.
    347 * It allocates a block of IRQs from the GIC-ITS.
    348 */
    349int fsl_mc_populate_irq_pool(struct fsl_mc_device *mc_bus_dev,
    350			     unsigned int irq_count)
    351{
    352	unsigned int i;
    353	struct fsl_mc_device_irq *irq_resources;
    354	struct fsl_mc_device_irq *mc_dev_irq;
    355	int error;
    356	struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
    357	struct fsl_mc_resource_pool *res_pool =
    358			&mc_bus->resource_pools[FSL_MC_POOL_IRQ];
    359
    360	/* do nothing if the IRQ pool is already populated */
    361	if (mc_bus->irq_resources)
    362		return 0;
    363
    364	if (irq_count == 0 ||
    365	    irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)
    366		return -EINVAL;
    367
    368	error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
    369	if (error < 0)
    370		return error;
    371
    372	irq_resources = devm_kcalloc(&mc_bus_dev->dev,
    373				     irq_count, sizeof(*irq_resources),
    374				     GFP_KERNEL);
    375	if (!irq_resources) {
    376		error = -ENOMEM;
    377		goto cleanup_msi_irqs;
    378	}
    379
    380	for (i = 0; i < irq_count; i++) {
    381		mc_dev_irq = &irq_resources[i];
    382
    383		/*
    384		 * NOTE: This mc_dev_irq's MSI addr/value pair will be set
    385		 * by the fsl_mc_msi_write_msg() callback
    386		 */
    387		mc_dev_irq->resource.type = res_pool->type;
    388		mc_dev_irq->resource.data = mc_dev_irq;
    389		mc_dev_irq->resource.parent_pool = res_pool;
    390		mc_dev_irq->virq = msi_get_virq(&mc_bus_dev->dev, i);
    391		mc_dev_irq->resource.id = mc_dev_irq->virq;
    392		INIT_LIST_HEAD(&mc_dev_irq->resource.node);
    393		list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
    394	}
    395
    396	res_pool->max_count = irq_count;
    397	res_pool->free_count = irq_count;
    398	mc_bus->irq_resources = irq_resources;
    399	return 0;
    400
    401cleanup_msi_irqs:
    402	fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
    403	return error;
    404}
    405EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
    406
    407/*
    408 * Teardown the interrupt pool associated with an fsl-mc bus.
    409 * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
    410 */
    411void fsl_mc_cleanup_irq_pool(struct fsl_mc_device *mc_bus_dev)
    412{
    413	struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
    414	struct fsl_mc_resource_pool *res_pool =
    415			&mc_bus->resource_pools[FSL_MC_POOL_IRQ];
    416
    417	if (!mc_bus->irq_resources)
    418		return;
    419
    420	if (res_pool->max_count == 0)
    421		return;
    422
    423	if (res_pool->free_count != res_pool->max_count)
    424		return;
    425
    426	INIT_LIST_HEAD(&res_pool->free_list);
    427	res_pool->max_count = 0;
    428	res_pool->free_count = 0;
    429	mc_bus->irq_resources = NULL;
    430	fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
    431}
    432EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
    433
    434/*
    435 * Allocate the IRQs required by a given fsl-mc device.
    436 */
    437int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
    438{
    439	int i;
    440	int irq_count;
    441	int res_allocated_count = 0;
    442	int error = -EINVAL;
    443	struct fsl_mc_device_irq **irqs = NULL;
    444	struct fsl_mc_bus *mc_bus;
    445	struct fsl_mc_resource_pool *res_pool;
    446
    447	if (mc_dev->irqs)
    448		return -EINVAL;
    449
    450	irq_count = mc_dev->obj_desc.irq_count;
    451	if (irq_count == 0)
    452		return -EINVAL;
    453
    454	if (is_fsl_mc_bus_dprc(mc_dev))
    455		mc_bus = to_fsl_mc_bus(mc_dev);
    456	else
    457		mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
    458
    459	if (!mc_bus->irq_resources)
    460		return -EINVAL;
    461
    462	res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
    463	if (res_pool->free_count < irq_count) {
    464		dev_err(&mc_dev->dev,
    465			"Not able to allocate %u irqs for device\n", irq_count);
    466		return -ENOSPC;
    467	}
    468
    469	irqs = devm_kcalloc(&mc_dev->dev, irq_count, sizeof(irqs[0]),
    470			    GFP_KERNEL);
    471	if (!irqs)
    472		return -ENOMEM;
    473
    474	for (i = 0; i < irq_count; i++) {
    475		struct fsl_mc_resource *resource;
    476
    477		error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
    478						 &resource);
    479		if (error < 0)
    480			goto error_resource_alloc;
    481
    482		irqs[i] = to_fsl_mc_irq(resource);
    483		res_allocated_count++;
    484
    485		irqs[i]->mc_dev = mc_dev;
    486		irqs[i]->dev_irq_index = i;
    487	}
    488
    489	mc_dev->irqs = irqs;
    490	return 0;
    491
    492error_resource_alloc:
    493	for (i = 0; i < res_allocated_count; i++) {
    494		irqs[i]->mc_dev = NULL;
    495		fsl_mc_resource_free(&irqs[i]->resource);
    496	}
    497
    498	return error;
    499}
    500EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
    501
    502/*
    503 * Frees the IRQs that were allocated for an fsl-mc device.
    504 */
    505void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
    506{
    507	int i;
    508	int irq_count;
    509	struct fsl_mc_bus *mc_bus;
    510	struct fsl_mc_device_irq **irqs = mc_dev->irqs;
    511
    512	if (!irqs)
    513		return;
    514
    515	irq_count = mc_dev->obj_desc.irq_count;
    516
    517	if (is_fsl_mc_bus_dprc(mc_dev))
    518		mc_bus = to_fsl_mc_bus(mc_dev);
    519	else
    520		mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
    521
    522	if (!mc_bus->irq_resources)
    523		return;
    524
    525	for (i = 0; i < irq_count; i++) {
    526		irqs[i]->mc_dev = NULL;
    527		fsl_mc_resource_free(&irqs[i]->resource);
    528	}
    529
    530	mc_dev->irqs = NULL;
    531}
    532EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
    533
    534void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
    535{
    536	int pool_type;
    537	struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
    538
    539	for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
    540		struct fsl_mc_resource_pool *res_pool =
    541		    &mc_bus->resource_pools[pool_type];
    542
    543		res_pool->type = pool_type;
    544		res_pool->max_count = 0;
    545		res_pool->free_count = 0;
    546		res_pool->mc_bus = mc_bus;
    547		INIT_LIST_HEAD(&res_pool->free_list);
    548		mutex_init(&res_pool->mutex);
    549	}
    550}
    551
    552static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
    553					 enum fsl_mc_pool_type pool_type)
    554{
    555	struct fsl_mc_resource *resource;
    556	struct fsl_mc_resource *next;
    557	struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
    558	struct fsl_mc_resource_pool *res_pool =
    559					&mc_bus->resource_pools[pool_type];
    560	int free_count = 0;
    561
    562	list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
    563		free_count++;
    564		devm_kfree(&mc_bus_dev->dev, resource);
    565	}
    566}
    567
    568void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
    569{
    570	int pool_type;
    571
    572	for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
    573		fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
    574}
    575
    576/*
    577 * fsl_mc_allocator_probe - callback invoked when an allocatable device is
    578 * being added to the system
    579 */
    580static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
    581{
    582	enum fsl_mc_pool_type pool_type;
    583	struct fsl_mc_device *mc_bus_dev;
    584	struct fsl_mc_bus *mc_bus;
    585	int error;
    586
    587	if (!fsl_mc_is_allocatable(mc_dev))
    588		return -EINVAL;
    589
    590	mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
    591	if (!dev_is_fsl_mc(&mc_bus_dev->dev))
    592		return -EINVAL;
    593
    594	mc_bus = to_fsl_mc_bus(mc_bus_dev);
    595	error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
    596	if (error < 0)
    597		return error;
    598
    599	error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
    600	if (error < 0)
    601		return error;
    602
    603	dev_dbg(&mc_dev->dev,
    604		"Allocatable fsl-mc device bound to fsl_mc_allocator driver");
    605	return 0;
    606}
    607
    608/*
    609 * fsl_mc_allocator_remove - callback invoked when an allocatable device is
    610 * being removed from the system
    611 */
    612static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
    613{
    614	int error;
    615
    616	if (!fsl_mc_is_allocatable(mc_dev))
    617		return -EINVAL;
    618
    619	if (mc_dev->resource) {
    620		error = fsl_mc_resource_pool_remove_device(mc_dev);
    621		if (error < 0)
    622			return error;
    623	}
    624
    625	dev_dbg(&mc_dev->dev,
    626		"Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
    627	return 0;
    628}
    629
    630static const struct fsl_mc_device_id match_id_table[] = {
    631	{
    632	 .vendor = FSL_MC_VENDOR_FREESCALE,
    633	 .obj_type = "dpbp",
    634	},
    635	{
    636	 .vendor = FSL_MC_VENDOR_FREESCALE,
    637	 .obj_type = "dpmcp",
    638	},
    639	{
    640	 .vendor = FSL_MC_VENDOR_FREESCALE,
    641	 .obj_type = "dpcon",
    642	},
    643	{.vendor = 0x0},
    644};
    645
    646static struct fsl_mc_driver fsl_mc_allocator_driver = {
    647	.driver = {
    648		   .name = "fsl_mc_allocator",
    649		   .pm = NULL,
    650		   },
    651	.match_id_table = match_id_table,
    652	.probe = fsl_mc_allocator_probe,
    653	.remove = fsl_mc_allocator_remove,
    654};
    655
    656int __init fsl_mc_allocator_driver_init(void)
    657{
    658	return fsl_mc_driver_register(&fsl_mc_allocator_driver);
    659}
    660
    661void fsl_mc_allocator_driver_exit(void)
    662{
    663	fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
    664}