~ubuntu-branches/ubuntu/oneiric/linux-ti-omap4/oneiric

« back to all changes in this revision

Viewing changes to drivers/dsp/syslink_old/multicore_ipc/heapmemmp_ioctl.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati, Paolo Pisati
  • Date: 2011-08-16 17:55:44 UTC
  • Revision ID: james.westby@ubuntu.com-20110816175544-ieu39dvqbiyufiwb
Tags: 3.0.0-1202.6
[ Paolo Pisati ]

* [Config] Sync config
* TI BSP update: kernel-tilt/tilt-3.0 @ f95dded2534d1d5a40fa4cb833699953d5f3e4de

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  heapmemmp_ioctl.c
 
3
 *
 
4
 *  Heap module manages fixed size buffers that can be used
 
5
 *  in a multiprocessor system with shared memory.
 
6
 *
 
7
 *  Copyright (C) 2008-2009 Texas Instruments, Inc.
 
8
 *
 
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.
 
12
 *
 
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
 
16
 *  PURPOSE.
 
17
 */
 
18
 
 
19
#include <linux/uaccess.h>
 
20
#include <linux/types.h>
 
21
#include <linux/bug.h>
 
22
#include <linux/fs.h>
 
23
#include <linux/mm.h>
 
24
#include <linux/slab.h>
 
25
 
 
26
#include <ipc.h>
 
27
#include <heap.h>
 
28
#include <heapmemmp_ioctl.h>
 
29
#include <sharedregion.h>
 
30
 
 
31
static struct resource_info *find_heapmemmp_resource(
 
32
                                        struct ipc_process_context *pr_ctxt,
 
33
                                        unsigned int cmd,
 
34
                                        struct heapmemmp_cmd_args *cargs)
 
35
{
 
36
        struct resource_info *info = NULL;
 
37
        bool found = false;
 
38
 
 
39
        spin_lock(&pr_ctxt->res_lock);
 
40
 
 
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) {
 
45
                        switch (cmd) {
 
46
                        case CMD_HEAPMEMMP_DELETE:
 
47
                        {
 
48
                                void *handle = args->args.delete.handle;
 
49
                                void *temp = cargs->args.delete.handle;
 
50
                                if (temp == handle)
 
51
                                        found = true;
 
52
                                break;
 
53
                        }
 
54
                        case CMD_HEAPMEMMP_DESTROY:
 
55
                        {
 
56
                                found = true;
 
57
                                break;
 
58
                        }
 
59
                        }
 
60
                        if (found == true)
 
61
                                break;
 
62
                }
 
63
        }
 
64
 
 
65
        spin_unlock(&pr_ctxt->res_lock);
 
66
 
 
67
        if (found == false)
 
68
                info = NULL;
 
69
 
 
70
        return info;
 
71
}
 
72
 
 
73
/*
 
74
 * ======== heapmemmp_ioctl_alloc ========
 
75
 *  Purpose:
 
76
 *  This ioctl interface to heapmemmp_alloc function
 
77
 */
 
78
static int heapmemmp_ioctl_alloc(struct heapmemmp_cmd_args *cargs)
 
79
{
 
80
        u32 *block_srptr = SHAREDREGION_INVALIDSRPTR;
 
81
        void *block;
 
82
        s32 index = SHAREDREGION_INVALIDREGIONID;
 
83
        s32 status = 0;
 
84
 
 
85
        block = heapmemmp_alloc(cargs->args.alloc.handle,
 
86
                                cargs->args.alloc.size,
 
87
                                cargs->args.alloc.align);
 
88
        if (block != NULL) {
 
89
                index = sharedregion_get_id(block);
 
90
                block_srptr = sharedregion_get_srptr(block, index);
 
91
        }
 
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
 
96
        */
 
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;
 
101
        return status;
 
102
}
 
103
 
 
104
/*
 
105
 * ======== heapmemmp_ioctl_free ========
 
106
 *  Purpose:
 
107
 *  This ioctl interface to heapmemmp_free function
 
108
 */
 
109
static int heapmemmp_ioctl_free(struct heapmemmp_cmd_args *cargs)
 
110
{
 
111
        char *block;
 
112
 
 
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);
 
117
        return 0;
 
118
}
 
119
 
 
120
/*
 
121
 * ======== heapmemmp_ioctl_params_init ========
 
122
 *  Purpose:
 
123
 *  This ioctl interface to heapmemmp_params_init function
 
124
 */
 
125
static int heapmemmp_ioctl_params_init(struct heapmemmp_cmd_args *cargs)
 
126
{
 
127
        struct heapmemmp_params params;
 
128
        s32 status = 0;
 
129
        u32 size;
 
130
 
 
131
        heapmemmp_params_init(&params);
 
132
        cargs->api_status = 0;
 
133
        size = copy_to_user((void __user *)cargs->args.params_init.params,
 
134
                                &params, sizeof(struct heapmemmp_params));
 
135
        if (size)
 
136
                status = -EFAULT;
 
137
 
 
138
        return status;
 
139
}
 
140
 
 
141
/*
 
142
 * ======== heapmemmp_ioctl_create ========
 
143
 *  Purpose:
 
144
 *  This ioctl interface to heapmemmp_create function
 
145
 */
 
146
static int heapmemmp_ioctl_create(struct heapmemmp_cmd_args *cargs)
 
147
{
 
148
        struct heapmemmp_params params;
 
149
        s32 status = 0;
 
150
        u32 size;
 
151
        void *handle = NULL;
 
152
 
 
153
        size = copy_from_user(&params, (void __user *)cargs->args.create.params,
 
154
                                sizeof(struct heapmemmp_params));
 
155
        if (size) {
 
156
                status = -EFAULT;
 
157
                goto exit;
 
158
        }
 
159
 
 
160
        if (cargs->args.create.name_len > 0) {
 
161
                params.name = kmalloc(cargs->args.create.name_len, GFP_KERNEL);
 
162
                if (params.name == NULL) {
 
163
                        status = -ENOMEM;
 
164
                        goto exit;
 
165
                }
 
166
 
 
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);
 
171
                if (size) {
 
172
                        status = -EFAULT;
 
173
                        goto name_from_usr_error;
 
174
                }
 
175
        }
 
176
 
 
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(&params);
 
181
        cargs->args.create.handle = handle;
 
182
        cargs->api_status  = 0;
 
183
 
 
184
name_from_usr_error:
 
185
        if (cargs->args.create.name_len > 0)
 
186
                kfree(params.name);
 
187
 
 
188
exit:
 
189
        return status;
 
190
}
 
191
 
 
192
 
 
193
/*
 
194
 * ======== heapmemmp_ioctl_delete ========
 
195
 *  Purpose:
 
196
 *  This ioctl interface to heapmemmp_delete function
 
197
 */
 
198
static int heapmemmp_ioctl_delete(struct heapmemmp_cmd_args *cargs)
 
199
{
 
200
        cargs->api_status = heapmemmp_delete(&cargs->args.delete.handle);
 
201
        return 0;
 
202
}
 
203
 
 
204
/*
 
205
 * ======== heapmemmp_ioctl_open ========
 
206
 *  Purpose:
 
207
 *  This ioctl interface to heapmemmp_open function
 
208
 */
 
209
static int heapmemmp_ioctl_open(struct heapmemmp_cmd_args *cargs)
 
210
{
 
211
        s32 status = 0;
 
212
        u32 size = 0;
 
213
        void *handle = NULL;
 
214
        char *name = NULL;
 
215
 
 
216
        if (cargs->args.open.name_len > 0) {
 
217
                name = kmalloc(cargs->args.open.name_len, GFP_KERNEL);
 
218
                if (name == NULL) {
 
219
                        status = -ENOMEM;
 
220
                        goto exit;
 
221
                }
 
222
 
 
223
                size = copy_from_user(name,
 
224
                                        (void __user *)cargs->args.open.name,
 
225
                                        cargs->args.open.name_len);
 
226
                if (size) {
 
227
                        status = -EFAULT;
 
228
                        goto exit;
 
229
                }
 
230
        }
 
231
 
 
232
        cargs->api_status = heapmemmp_open(cargs->args.open.name, &handle);
 
233
        cargs->args.open.handle = handle;
 
234
 
 
235
        if (cargs->args.open.name_len > 0)
 
236
                kfree(name);
 
237
exit:
 
238
        return status;
 
239
}
 
240
 
 
241
/*
 
242
 * ======== heapmemmp_ioctl_open_by_addr ========
 
243
 *  Purpose:
 
244
 *  This ioctl interface to heapmemmp_open_by_addr function
 
245
 */
 
246
static int heapmemmp_ioctl_open_by_addr(struct heapmemmp_cmd_args *cargs)
 
247
{
 
248
        void *handle = NULL;
 
249
 
 
250
        cargs->api_status = heapmemmp_open_by_addr((void *)
 
251
                                cargs->args.open_by_addr.shared_addr_srptr,
 
252
                                                                &handle);
 
253
        cargs->args.open_by_addr.handle = handle;
 
254
 
 
255
        return 0;
 
256
}
 
257
 
 
258
 
 
259
/*
 
260
 * ======== heapmemmp_ioctl_close ========
 
261
 *  Purpose:
 
262
 *  This ioctl interface to heapmemmp_close function
 
263
 */
 
264
static int heapmemmp_ioctl_close(struct heapmemmp_cmd_args *cargs)
 
265
{
 
266
        cargs->api_status = heapmemmp_close(cargs->args.close.handle);
 
267
        return 0;
 
268
}
 
269
 
 
270
/*
 
271
 * ======== heapmemmp_ioctl_shared_mem_req ========
 
272
 *  Purpose:
 
273
 *  This ioctl interface to heapmemmp_shared_mem_req function
 
274
 */
 
275
static int heapmemmp_ioctl_shared_mem_req(struct heapmemmp_cmd_args *cargs)
 
276
{
 
277
        struct heapmemmp_params params;
 
278
        s32 status = 0;
 
279
        ulong size;
 
280
        u32 bytes;
 
281
 
 
282
        size = copy_from_user(&params,
 
283
                        (void __user *)cargs->args.shared_mem_req.params,
 
284
                        sizeof(struct heapmemmp_params));
 
285
        if (size) {
 
286
                status = -EFAULT;
 
287
                goto exit;
 
288
        }
 
289
        if (params.shared_addr != NULL) {
 
290
                params.shared_addr = sharedregion_get_ptr(
 
291
                                cargs->args.shared_mem_req.shared_addr_srptr);
 
292
        }
 
293
        bytes = heapmemmp_shared_mem_req(&params);
 
294
        cargs->args.shared_mem_req.bytes = bytes;
 
295
        cargs->api_status = 0;
 
296
 
 
297
exit:
 
298
        return status;
 
299
}
 
300
 
 
301
 
 
302
/*
 
303
 * ======== heapmemmp_ioctl_get_config ========
 
304
 *  Purpose:
 
305
 *  This ioctl interface to heapmemmp_get_config function
 
306
 */
 
307
static int heapmemmp_ioctl_get_config(struct heapmemmp_cmd_args *cargs)
 
308
{
 
309
        struct heapmemmp_config config;
 
310
        s32 status = 0;
 
311
        ulong size;
 
312
 
 
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));
 
316
        if (size)
 
317
                status = -EFAULT;
 
318
 
 
319
        return status;
 
320
}
 
321
 
 
322
/*
 
323
 * ======== heapmemmp_ioctl_setup ========
 
324
 *  Purpose:
 
325
 *  This ioctl interface to heapmemmp_setup function
 
326
 */
 
327
static int heapmemmp_ioctl_setup(struct heapmemmp_cmd_args *cargs)
 
328
{
 
329
        struct heapmemmp_config config;
 
330
        s32 status = 0;
 
331
        ulong size;
 
332
 
 
333
        size = copy_from_user(&config, (void __user *)cargs->args.setup.config,
 
334
                                        sizeof(struct heapmemmp_config));
 
335
        if (size) {
 
336
                status = -EFAULT;
 
337
                goto exit;
 
338
        }
 
339
 
 
340
        cargs->api_status = heapmemmp_setup(&config);
 
341
 
 
342
exit:
 
343
        return status;
 
344
}
 
345
/*
 
346
 * ======== heapmemmp_ioctl_destroy ========
 
347
 *  Purpose:
 
348
 *  This ioctl interface to heapmemmp_destroy function
 
349
 */
 
350
static int heapmemmp_ioctl_destroy(struct heapmemmp_cmd_args *cargs)
 
351
{
 
352
        cargs->api_status = heapmemmp_destroy();
 
353
        return 0;
 
354
}
 
355
 
 
356
 
 
357
/*
 
358
 * ======== heapmemmp_ioctl_get_stats ========
 
359
 *  Purpose:
 
360
 *  This ioctl interface to heapmemmp_get_stats function
 
361
 */
 
362
static int heapmemmp_ioctl_get_stats(struct heapmemmp_cmd_args *cargs)
 
363
{
 
364
        struct memory_stats stats;
 
365
        s32 status = 0;
 
366
        ulong size;
 
367
 
 
368
        heapmemmp_get_stats(cargs->args.get_stats.handle, &stats);
 
369
        cargs->api_status = 0;
 
370
 
 
371
        size = copy_to_user((void __user *)cargs->args.get_stats.stats, &stats,
 
372
                                        sizeof(struct memory_stats));
 
373
        if (size)
 
374
                status = -EFAULT;
 
375
 
 
376
        return status;
 
377
}
 
378
 
 
379
/*
 
380
 * ======== heapmemmp_ioctl_get_extended_stats ========
 
381
 *  Purpose:
 
382
 *  This ioctl interface to heapmemmp_get_extended_stats function
 
383
 */
 
384
static int heapmemmp_ioctl_get_extended_stats(struct heapmemmp_cmd_args *cargs)
 
385
{
 
386
        struct heapmemmp_extended_stats stats;
 
387
        s32 status = 0;
 
388
        ulong size;
 
389
 
 
390
        heapmemmp_get_extended_stats(cargs->args.get_extended_stats.handle,
 
391
                                                                &stats);
 
392
        cargs->api_status = 0;
 
393
 
 
394
        size = copy_to_user((void __user *)cargs->args.get_extended_stats.stats,
 
395
                                &stats,
 
396
                                sizeof(struct heapmemmp_extended_stats));
 
397
        if (size)
 
398
                status = -EFAULT;
 
399
 
 
400
        return status;
 
401
}
 
402
 
 
403
/*
 
404
 * ======== heapmemmp_ioctl_restore ========
 
405
 *  Purpose:
 
406
 *  This ioctl interface to heapmemmp_get_extended_stats function
 
407
 */
 
408
static int heapmemmp_ioctl_restore(struct heapmemmp_cmd_args *cargs)
 
409
{
 
410
        heapmemmp_restore(cargs->args.restore.handle);
 
411
        cargs->api_status = 0;
 
412
        return 0;
 
413
}
 
414
 
 
415
/*
 
416
 * ======== heapmemmp_ioctl ========
 
417
 *  Purpose:
 
418
 *  This ioctl interface for heapmem module
 
419
 */
 
420
int heapmemmp_ioctl(struct inode *pinode, struct file *filp,
 
421
                        unsigned int cmd, unsigned long  args, bool user)
 
422
{
 
423
        s32 status = 0;
 
424
        s32 size = 0;
 
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;
 
430
 
 
431
        if (user == true) {
 
432
#ifdef CONFIG_SYSLINK_RECOVERY
 
433
                if (ipc_recovering()) {
 
434
                        status = -EIO;
 
435
                        goto exit;
 
436
                }
 
437
#endif
 
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));
 
442
 
 
443
                if (status) {
 
444
                        status = -EFAULT;
 
445
                        goto exit;
 
446
                }
 
447
 
 
448
                /* Copy the full args from user-side */
 
449
                size = copy_from_user(&cargs, uarg,
 
450
                                        sizeof(struct heapmemmp_cmd_args));
 
451
                if (size) {
 
452
                        status = -EFAULT;
 
453
                        goto exit;
 
454
                }
 
455
        } else {
 
456
                if (args != 0)
 
457
                        memcpy(&cargs, (void *)args,
 
458
                                sizeof(struct heapmemmp_cmd_args));
 
459
        }
 
460
 
 
461
        switch (cmd) {
 
462
        case CMD_HEAPMEMMP_ALLOC:
 
463
                status = heapmemmp_ioctl_alloc(&cargs);
 
464
                break;
 
465
 
 
466
        case CMD_HEAPMEMMP_FREE:
 
467
                status = heapmemmp_ioctl_free(&cargs);
 
468
                break;
 
469
 
 
470
        case CMD_HEAPMEMMP_PARAMS_INIT:
 
471
                status = heapmemmp_ioctl_params_init(&cargs);
 
472
                break;
 
473
 
 
474
        case CMD_HEAPMEMMP_CREATE:
 
475
                status = heapmemmp_ioctl_create(&cargs);
 
476
                if (status >= 0) {
 
477
                        struct heapmemmp_cmd_args *temp = kmalloc(
 
478
                                        sizeof(struct heapmemmp_cmd_args),
 
479
                                        GFP_KERNEL);
 
480
                        if (WARN_ON(!temp)) {
 
481
                                status = -ENOMEM;
 
482
                                goto exit;
 
483
                        }
 
484
                        temp->args.delete.handle = cargs.args.create.handle;
 
485
                        add_pr_res(pr_ctxt, CMD_HEAPMEMMP_DELETE, (void *)temp);
 
486
                }
 
487
                break;
 
488
 
 
489
        case CMD_HEAPMEMMP_DELETE:
 
490
        {
 
491
                struct resource_info *info = NULL;
 
492
                info = find_heapmemmp_resource(pr_ctxt,
 
493
                                                CMD_HEAPMEMMP_DELETE,
 
494
                                                &cargs);
 
495
                status  = heapmemmp_ioctl_delete(&cargs);
 
496
                remove_pr_res(pr_ctxt, info);
 
497
                break;
 
498
        }
 
499
 
 
500
        case CMD_HEAPMEMMP_OPEN:
 
501
                status  = heapmemmp_ioctl_open(&cargs);
 
502
                break;
 
503
 
 
504
        case CMD_HEAPMEMMP_OPENBYADDR:
 
505
                status  = heapmemmp_ioctl_open_by_addr(&cargs);
 
506
                break;
 
507
 
 
508
        case CMD_HEAPMEMMP_CLOSE:
 
509
                status = heapmemmp_ioctl_close(&cargs);
 
510
                break;
 
511
 
 
512
        case CMD_HEAPMEMMP_SHAREDMEMREQ:
 
513
                status = heapmemmp_ioctl_shared_mem_req(&cargs);
 
514
                break;
 
515
 
 
516
        case CMD_HEAPMEMMP_GETCONFIG:
 
517
                status = heapmemmp_ioctl_get_config(&cargs);
 
518
                break;
 
519
 
 
520
        case CMD_HEAPMEMMP_SETUP:
 
521
                status = heapmemmp_ioctl_setup(&cargs);
 
522
                if (status >= 0)
 
523
                        add_pr_res(pr_ctxt, CMD_HEAPMEMMP_DESTROY, NULL);
 
524
                break;
 
525
 
 
526
        case CMD_HEAPMEMMP_DESTROY:
 
527
        {
 
528
                struct resource_info *info = NULL;
 
529
                info = find_heapmemmp_resource(pr_ctxt,
 
530
                                                CMD_HEAPMEMMP_DESTROY,
 
531
                                                &cargs);
 
532
                status = heapmemmp_ioctl_destroy(&cargs);
 
533
                remove_pr_res(pr_ctxt, info);
 
534
                break;
 
535
        }
 
536
 
 
537
        case CMD_HEAPMEMMP_GETSTATS:
 
538
                status = heapmemmp_ioctl_get_stats(&cargs);
 
539
                break;
 
540
 
 
541
        case CMD_HEAPMEMMP_GETEXTENDEDSTATS:
 
542
                status = heapmemmp_ioctl_get_extended_stats(&cargs);
 
543
                break;
 
544
 
 
545
        case CMD_HEAPMEMMP_RESTORE:
 
546
                status = heapmemmp_ioctl_restore(&cargs);
 
547
                break;
 
548
 
 
549
        default:
 
550
                WARN_ON(cmd);
 
551
                status = -ENOTTY;
 
552
                break;
 
553
        }
 
554
 
 
555
        if (user == true) {
 
556
                /* Copy the full args to the user-side. */
 
557
                size = copy_to_user(uarg, &cargs,
 
558
                                        sizeof(struct heapmemmp_cmd_args));
 
559
                if (size) {
 
560
                        status = -EFAULT;
 
561
                        goto exit;
 
562
                }
 
563
        }
 
564
 
 
565
exit:
 
566
        return status;
 
567
}