4
* Heap module manages fixed size buffers that can be used
5
* in a multiprocessor system with shared memory.
7
* Copyright (C) 2008-2009 Texas Instruments, Inc.
9
* This package is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License version 2 as
11
* published by the Free Software Foundation.
13
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
19
#include <linux/uaccess.h>
20
#include <linux/types.h>
21
#include <linux/bug.h>
24
#include <linux/slab.h>
28
#include <heapmemmp_ioctl.h>
29
#include <sharedregion.h>
31
static struct resource_info *find_heapmemmp_resource(
32
struct ipc_process_context *pr_ctxt,
34
struct heapmemmp_cmd_args *cargs)
36
struct resource_info *info = NULL;
39
spin_lock(&pr_ctxt->res_lock);
41
list_for_each_entry(info, &pr_ctxt->resources, res) {
42
struct heapmemmp_cmd_args *args =
43
(struct heapmemmp_cmd_args *)info->data;
44
if (info->cmd == cmd) {
46
case CMD_HEAPMEMMP_DELETE:
48
void *handle = args->args.delete.handle;
49
void *temp = cargs->args.delete.handle;
54
case CMD_HEAPMEMMP_DESTROY:
65
spin_unlock(&pr_ctxt->res_lock);
74
* ======== heapmemmp_ioctl_alloc ========
76
* This ioctl interface to heapmemmp_alloc function
78
static int heapmemmp_ioctl_alloc(struct heapmemmp_cmd_args *cargs)
80
u32 *block_srptr = SHAREDREGION_INVALIDSRPTR;
82
s32 index = SHAREDREGION_INVALIDREGIONID;
85
block = heapmemmp_alloc(cargs->args.alloc.handle,
86
cargs->args.alloc.size,
87
cargs->args.alloc.align);
89
index = sharedregion_get_id(block);
90
block_srptr = sharedregion_get_srptr(block, index);
92
/* The error on above fn will be a null ptr. We are not
93
checking that condition here. We are passing whatever
94
we are getting from the heapmem module. So IOCTL will succed,
95
but the actual fn might be failed inside heapmem
97
BUG_ON(index == SHAREDREGION_INVALIDREGIONID);
98
cargs->args.alloc.block_srptr = block_srptr;
99
BUG_ON(cargs->args.alloc.block_srptr == SHAREDREGION_INVALIDSRPTR);
100
cargs->api_status = 0;
105
* ======== heapmemmp_ioctl_free ========
107
* This ioctl interface to heapmemmp_free function
109
static int heapmemmp_ioctl_free(struct heapmemmp_cmd_args *cargs)
113
block = sharedregion_get_ptr(cargs->args.free.block_srptr);
114
BUG_ON(block == NULL);
115
cargs->api_status = heapmemmp_free(cargs->args.free.handle, block,
116
cargs->args.free.size);
121
* ======== heapmemmp_ioctl_params_init ========
123
* This ioctl interface to heapmemmp_params_init function
125
static int heapmemmp_ioctl_params_init(struct heapmemmp_cmd_args *cargs)
127
struct heapmemmp_params params;
131
heapmemmp_params_init(¶ms);
132
cargs->api_status = 0;
133
size = copy_to_user((void __user *)cargs->args.params_init.params,
134
¶ms, sizeof(struct heapmemmp_params));
142
* ======== heapmemmp_ioctl_create ========
144
* This ioctl interface to heapmemmp_create function
146
static int heapmemmp_ioctl_create(struct heapmemmp_cmd_args *cargs)
148
struct heapmemmp_params params;
153
size = copy_from_user(¶ms, (void __user *)cargs->args.create.params,
154
sizeof(struct heapmemmp_params));
160
if (cargs->args.create.name_len > 0) {
161
params.name = kmalloc(cargs->args.create.name_len, GFP_KERNEL);
162
if (params.name == NULL) {
167
params.name[cargs->args.create.name_len] = '\0';
168
size = copy_from_user(params.name,
169
(void __user *)cargs->args.create.params->name,
170
cargs->args.create.name_len);
173
goto name_from_usr_error;
177
params.shared_addr = sharedregion_get_ptr((u32 *)
178
cargs->args.create.shared_addr_srptr);
179
params.gate = cargs->args.create.knl_gate;
180
handle = heapmemmp_create(¶ms);
181
cargs->args.create.handle = handle;
182
cargs->api_status = 0;
185
if (cargs->args.create.name_len > 0)
194
* ======== heapmemmp_ioctl_delete ========
196
* This ioctl interface to heapmemmp_delete function
198
static int heapmemmp_ioctl_delete(struct heapmemmp_cmd_args *cargs)
200
cargs->api_status = heapmemmp_delete(&cargs->args.delete.handle);
205
* ======== heapmemmp_ioctl_open ========
207
* This ioctl interface to heapmemmp_open function
209
static int heapmemmp_ioctl_open(struct heapmemmp_cmd_args *cargs)
216
if (cargs->args.open.name_len > 0) {
217
name = kmalloc(cargs->args.open.name_len, GFP_KERNEL);
223
size = copy_from_user(name,
224
(void __user *)cargs->args.open.name,
225
cargs->args.open.name_len);
232
cargs->api_status = heapmemmp_open(cargs->args.open.name, &handle);
233
cargs->args.open.handle = handle;
235
if (cargs->args.open.name_len > 0)
242
* ======== heapmemmp_ioctl_open_by_addr ========
244
* This ioctl interface to heapmemmp_open_by_addr function
246
static int heapmemmp_ioctl_open_by_addr(struct heapmemmp_cmd_args *cargs)
250
cargs->api_status = heapmemmp_open_by_addr((void *)
251
cargs->args.open_by_addr.shared_addr_srptr,
253
cargs->args.open_by_addr.handle = handle;
260
* ======== heapmemmp_ioctl_close ========
262
* This ioctl interface to heapmemmp_close function
264
static int heapmemmp_ioctl_close(struct heapmemmp_cmd_args *cargs)
266
cargs->api_status = heapmemmp_close(cargs->args.close.handle);
271
* ======== heapmemmp_ioctl_shared_mem_req ========
273
* This ioctl interface to heapmemmp_shared_mem_req function
275
static int heapmemmp_ioctl_shared_mem_req(struct heapmemmp_cmd_args *cargs)
277
struct heapmemmp_params params;
282
size = copy_from_user(¶ms,
283
(void __user *)cargs->args.shared_mem_req.params,
284
sizeof(struct heapmemmp_params));
289
if (params.shared_addr != NULL) {
290
params.shared_addr = sharedregion_get_ptr(
291
cargs->args.shared_mem_req.shared_addr_srptr);
293
bytes = heapmemmp_shared_mem_req(¶ms);
294
cargs->args.shared_mem_req.bytes = bytes;
295
cargs->api_status = 0;
303
* ======== heapmemmp_ioctl_get_config ========
305
* This ioctl interface to heapmemmp_get_config function
307
static int heapmemmp_ioctl_get_config(struct heapmemmp_cmd_args *cargs)
309
struct heapmemmp_config config;
313
cargs->api_status = heapmemmp_get_config(&config);
314
size = copy_to_user((void __user *)cargs->args.get_config.config,
315
&config, sizeof(struct heapmemmp_config));
323
* ======== heapmemmp_ioctl_setup ========
325
* This ioctl interface to heapmemmp_setup function
327
static int heapmemmp_ioctl_setup(struct heapmemmp_cmd_args *cargs)
329
struct heapmemmp_config config;
333
size = copy_from_user(&config, (void __user *)cargs->args.setup.config,
334
sizeof(struct heapmemmp_config));
340
cargs->api_status = heapmemmp_setup(&config);
346
* ======== heapmemmp_ioctl_destroy ========
348
* This ioctl interface to heapmemmp_destroy function
350
static int heapmemmp_ioctl_destroy(struct heapmemmp_cmd_args *cargs)
352
cargs->api_status = heapmemmp_destroy();
358
* ======== heapmemmp_ioctl_get_stats ========
360
* This ioctl interface to heapmemmp_get_stats function
362
static int heapmemmp_ioctl_get_stats(struct heapmemmp_cmd_args *cargs)
364
struct memory_stats stats;
368
heapmemmp_get_stats(cargs->args.get_stats.handle, &stats);
369
cargs->api_status = 0;
371
size = copy_to_user((void __user *)cargs->args.get_stats.stats, &stats,
372
sizeof(struct memory_stats));
380
* ======== heapmemmp_ioctl_get_extended_stats ========
382
* This ioctl interface to heapmemmp_get_extended_stats function
384
static int heapmemmp_ioctl_get_extended_stats(struct heapmemmp_cmd_args *cargs)
386
struct heapmemmp_extended_stats stats;
390
heapmemmp_get_extended_stats(cargs->args.get_extended_stats.handle,
392
cargs->api_status = 0;
394
size = copy_to_user((void __user *)cargs->args.get_extended_stats.stats,
396
sizeof(struct heapmemmp_extended_stats));
404
* ======== heapmemmp_ioctl_restore ========
406
* This ioctl interface to heapmemmp_get_extended_stats function
408
static int heapmemmp_ioctl_restore(struct heapmemmp_cmd_args *cargs)
410
heapmemmp_restore(cargs->args.restore.handle);
411
cargs->api_status = 0;
416
* ======== heapmemmp_ioctl ========
418
* This ioctl interface for heapmem module
420
int heapmemmp_ioctl(struct inode *pinode, struct file *filp,
421
unsigned int cmd, unsigned long args, bool user)
425
struct heapmemmp_cmd_args __user *uarg =
426
(struct heapmemmp_cmd_args __user *)args;
427
struct heapmemmp_cmd_args cargs;
428
struct ipc_process_context *pr_ctxt =
429
(struct ipc_process_context *)filp->private_data;
432
#ifdef CONFIG_SYSLINK_RECOVERY
433
if (ipc_recovering()) {
438
if (_IOC_DIR(cmd) & _IOC_READ)
439
status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
440
else if (_IOC_DIR(cmd) & _IOC_WRITE)
441
status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
448
/* Copy the full args from user-side */
449
size = copy_from_user(&cargs, uarg,
450
sizeof(struct heapmemmp_cmd_args));
457
memcpy(&cargs, (void *)args,
458
sizeof(struct heapmemmp_cmd_args));
462
case CMD_HEAPMEMMP_ALLOC:
463
status = heapmemmp_ioctl_alloc(&cargs);
466
case CMD_HEAPMEMMP_FREE:
467
status = heapmemmp_ioctl_free(&cargs);
470
case CMD_HEAPMEMMP_PARAMS_INIT:
471
status = heapmemmp_ioctl_params_init(&cargs);
474
case CMD_HEAPMEMMP_CREATE:
475
status = heapmemmp_ioctl_create(&cargs);
477
struct heapmemmp_cmd_args *temp = kmalloc(
478
sizeof(struct heapmemmp_cmd_args),
480
if (WARN_ON(!temp)) {
484
temp->args.delete.handle = cargs.args.create.handle;
485
add_pr_res(pr_ctxt, CMD_HEAPMEMMP_DELETE, (void *)temp);
489
case CMD_HEAPMEMMP_DELETE:
491
struct resource_info *info = NULL;
492
info = find_heapmemmp_resource(pr_ctxt,
493
CMD_HEAPMEMMP_DELETE,
495
status = heapmemmp_ioctl_delete(&cargs);
496
remove_pr_res(pr_ctxt, info);
500
case CMD_HEAPMEMMP_OPEN:
501
status = heapmemmp_ioctl_open(&cargs);
504
case CMD_HEAPMEMMP_OPENBYADDR:
505
status = heapmemmp_ioctl_open_by_addr(&cargs);
508
case CMD_HEAPMEMMP_CLOSE:
509
status = heapmemmp_ioctl_close(&cargs);
512
case CMD_HEAPMEMMP_SHAREDMEMREQ:
513
status = heapmemmp_ioctl_shared_mem_req(&cargs);
516
case CMD_HEAPMEMMP_GETCONFIG:
517
status = heapmemmp_ioctl_get_config(&cargs);
520
case CMD_HEAPMEMMP_SETUP:
521
status = heapmemmp_ioctl_setup(&cargs);
523
add_pr_res(pr_ctxt, CMD_HEAPMEMMP_DESTROY, NULL);
526
case CMD_HEAPMEMMP_DESTROY:
528
struct resource_info *info = NULL;
529
info = find_heapmemmp_resource(pr_ctxt,
530
CMD_HEAPMEMMP_DESTROY,
532
status = heapmemmp_ioctl_destroy(&cargs);
533
remove_pr_res(pr_ctxt, info);
537
case CMD_HEAPMEMMP_GETSTATS:
538
status = heapmemmp_ioctl_get_stats(&cargs);
541
case CMD_HEAPMEMMP_GETEXTENDEDSTATS:
542
status = heapmemmp_ioctl_get_extended_stats(&cargs);
545
case CMD_HEAPMEMMP_RESTORE:
546
status = heapmemmp_ioctl_restore(&cargs);
556
/* Copy the full args to the user-side. */
557
size = copy_to_user(uarg, &cargs,
558
sizeof(struct heapmemmp_cmd_args));