staging: tidspbridge: fix kernel oops in bridge_io_get_proc_load
authorIonut Nicu <ionut.nicu@gmail.com>
Fri, 5 Nov 2010 17:01:50 +0000 (17:01 +0000)
committerOmar Ramirez Luna <omar.ramirez@ti.com>
Sat, 5 Feb 2011 02:11:24 +0000 (20:11 -0600)
The DSP shared memory area gets initialized only when
a COFF file is loaded.

If bridge_io_get_proc_load is called before loading a base
image into the DSP, the shared_mem member of the io manager
will be NULL, resulting in a kernel oops when it's dereferenced.

Also made some coding style changes to bridge_io_create.

Signed-off-by: Ionut Nicu <ionut.nicu@mindbit.ro>
Signed-off-by: Omar Ramirez Luna <omar.ramirez@ti.com>
drivers/staging/tidspbridge/core/io_sm.c

index 27e0aa81a584b61f16626e788cce3981b0a9f75a..9cea3eacf1a87ebb1a00f585fbd43a8d522de75d 100644 (file)
@@ -167,57 +167,41 @@ int bridge_io_create(struct io_mgr **io_man,
                            struct dev_object *hdev_obj,
                            const struct io_attrs *mgr_attrts)
 {
-       int status = 0;
        struct io_mgr *pio_mgr = NULL;
-       struct shm *shared_mem = NULL;
        struct bridge_dev_context *hbridge_context = NULL;
        struct cfg_devnode *dev_node_obj;
        struct chnl_mgr *hchnl_mgr;
        u8 dev_type;
 
        /* Check requirements */
-       if (!io_man || !mgr_attrts || mgr_attrts->word_size == 0) {
-               status = -EFAULT;
-               goto func_end;
-       }
+       if (!io_man || !mgr_attrts || mgr_attrts->word_size == 0)
+               return -EFAULT;
+
+       *io_man = NULL;
+
        dev_get_chnl_mgr(hdev_obj, &hchnl_mgr);
-       if (!hchnl_mgr || hchnl_mgr->hio_mgr) {
-               status = -EFAULT;
-               goto func_end;
-       }
+       if (!hchnl_mgr || hchnl_mgr->hio_mgr)
+               return -EFAULT;
+
        /*
         * Message manager will be created when a file is loaded, since
         * size of message buffer in shared memory is configurable in
         * the base image.
         */
        dev_get_bridge_context(hdev_obj, &hbridge_context);
-       if (!hbridge_context) {
-               status = -EFAULT;
-               goto func_end;
-       }
+       if (!hbridge_context)
+               return -EFAULT;
+
        dev_get_dev_type(hdev_obj, &dev_type);
-       /*
-        * DSP shared memory area will get set properly when
-        * a program is loaded. They are unknown until a COFF file is
-        * loaded. I chose the value -1 because it was less likely to be
-        * a valid address than 0.
-        */
-       shared_mem = (struct shm *)-1;
 
        /* Allocate IO manager object */
        pio_mgr = kzalloc(sizeof(struct io_mgr), GFP_KERNEL);
-       if (pio_mgr == NULL) {
-               status = -ENOMEM;
-               goto func_end;
-       }
+       if (!pio_mgr)
+               return -ENOMEM;
 
        /* Initialize chnl_mgr object */
-#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG)
-       pio_mgr->pmsg = NULL;
-#endif
        pio_mgr->hchnl_mgr = hchnl_mgr;
        pio_mgr->word_size = mgr_attrts->word_size;
-       pio_mgr->shared_mem = shared_mem;
 
        if (dev_type == DSP_UNIT) {
                /* Create an IO DPC */
@@ -229,29 +213,24 @@ int bridge_io_create(struct io_mgr **io_man,
 
                spin_lock_init(&pio_mgr->dpc_lock);
 
-               status = dev_get_dev_node(hdev_obj, &dev_node_obj);
+               if (dev_get_dev_node(hdev_obj, &dev_node_obj)) {
+                       bridge_io_destroy(pio_mgr);
+                       return -EIO;
+               }
        }
 
-       if (!status) {
-               pio_mgr->hbridge_context = hbridge_context;
-               pio_mgr->shared_irq = mgr_attrts->irq_shared;
-               if (dsp_wdt_init())
-                       status = -EPERM;
-       } else {
-               status = -EIO;
-       }
-func_end:
-       if (status) {
-               /* Cleanup */
+       pio_mgr->hbridge_context = hbridge_context;
+       pio_mgr->shared_irq = mgr_attrts->irq_shared;
+       if (dsp_wdt_init()) {
                bridge_io_destroy(pio_mgr);
-               if (io_man)
-                       *io_man = NULL;
-       } else {
-               /* Return IO manager object to caller... */
-               hchnl_mgr->hio_mgr = pio_mgr;
-               *io_man = pio_mgr;
+               return -EPERM;
        }
-       return status;
+
+       /* Return IO manager object to caller... */
+       hchnl_mgr->hio_mgr = pio_mgr;
+       *io_man = pio_mgr;
+
+       return 0;
 }
 
 /*
@@ -1714,6 +1693,9 @@ int io_sh_msetting(struct io_mgr *hio_mgr, u8 desc, void *pargs)
 int bridge_io_get_proc_load(struct io_mgr *hio_mgr,
                                struct dsp_procloadstat *proc_lstat)
 {
+       if (!hio_mgr->shared_mem)
+               return -EFAULT;
+
        proc_lstat->curr_load =
                        hio_mgr->shared_mem->load_mon_info.curr_dsp_load;
        proc_lstat->predicted_load =