Skip to content

tmf8829_driver.c:1002 early error paths unlock a non-locked mutex in tmf8829_probe #6

@imtjr

Description

@imtjr
static int tmf8829_probe(tmf8829_chip *chip)
{
    int error = -1;
    void *poll_prop_ptr = NULL;

    /* Platform Setup */
    mutex_init(&chip->lock);
    mutex_init(&chip->fifo_lock);
    

    chip->pdata = &tmf8829_pdata;
    error = tof_get_gpio_config(chip);
    if (error) {
        dev_err(&chip->client->dev, "Error gpio config.\n");
        goto gpio_err;
    }
    
    if (writePin( chip->pdata->gpiod_enable, 1)) {
        dev_err(&chip->client->dev, "Chip enable failed.\n");
        goto gpio_err;
    }
    dev_info(&chip->client->dev, "Chip enable done.\n");

    /* Setup IRQ Handling */
    poll_prop_ptr = (void *)of_get_property(chip->client->dev.of_node, TOF_PROP_NAME_POLLIO, NULL);
    chip->poll_period = poll_prop_ptr ? be32_to_cpup(poll_prop_ptr) : 0;

    if(chip->poll_period == 0) { /* Use Interrupt I/O */
        if (chip->pdata->gpiod_interrupt) {
            error = tof_request_irq(chip);
            if (error) {
                dev_err(&chip->client->dev, "Interrupt request failed.\n");
                goto gpio_err;
            }
        }
    }
    else { /* Polled I/O */
        chip->app_poll_irq = kthread_run(tmf8829_app_poll_irq_thread, (void *)chip, "tof-irq_poll");
        if (IS_ERR(chip->app_poll_irq)) {
            dev_err(&chip->client->dev, "Error starting IRQ polling thread.\n");
            error = PTR_ERR(chip->app_poll_irq);
            goto gpio_err;
        }
    }

    /* initialize kfifo for frame output */
    INIT_KFIFO(chip->tof_output_fifo);
    chip->tof_output_frame.frame.frameId = TMF8829_COM_RESULT__no_frame;
    chip->tof_output_frame.frame.frameNumber = 0;
    chip->tof_output_frame.frame.clkcorr_lsb = 0;
    chip->tof_output_frame.frame.clkcorr_msb = 0;
    chip->tof_output_frame.frame.reserved_0  = 0x77;
    chip->tof_output_frame.frame.reserved_1  = 0x77;
    chip->tof_output_frame.frame.payload_lsb = 0;
    chip->tof_output_frame.frame.payload_msb = 0;

    /* TMF8829 Setup */
    AMS_MUTEX_LOCK(&chip->lock);

    tmf8829Initialise(&chip->tof_core);
    tmf8829SetLogLevel(&chip->tof_core, APP_LOG_LEVEL);
    delayInMicroseconds(ENABLE_TIME_MS * 1000);
    tmf8829PowerUp(&chip->tof_core);

    if (tmf8829IsCpuReady(&chip->tof_core, CPU_READY_TIME_MS) == 0) {
        dev_err(&chip->client->dev, "CPU is not ready.\n");
        error = 5;
        goto gen_err;
    }

    /* switch off unused communication interface */
#ifdef USE_I2C
    error = tmf8829BootloaderCmdSpiOff(&chip->tof_core);
#endif
#ifdef USE_SPI
    error = tmf8829BootloaderCmdI2cOff(&chip->tof_core);
#endif

    if (error != BL_SUCCESS_OK) {
        dev_err(&chip->client->dev, "error disable communication interface .\n");
        goto gen_err;
    }

    error = firmware_download(&chip->client->dev); 
    
    if (error != 0) {
        goto gen_err;
    }
    else {
        dev_info(&chip->client->dev, "Firmware download done.\n");
    }

    if (tmf8829GetConfiguration(&chip->tof_core) != APP_SUCCESS_OK) {
        dev_err(&chip->client->dev, "Read device configuration error.\n");
        goto gen_err;
    }

    if (tmf8829ReadDeviceInfo( &chip->tof_core) != APP_SUCCESS_OK) {
        dev_err(&chip->client->dev, "Read device information.\n");
        goto gen_err;
    }
    chip->tof_core.cyclicRunning = 0;
    tmf8829ClrAndEnableInterrupts( &chip->tof_core, TMF8829_APP_INT_ALL );

    /* Sysfs Setup */
    error = sysfs_create_groups(&chip->client->dev.kobj, tmf8829_attr_groups);
    if (error) {
        dev_err(&chip->client->dev, "Error creating sysfs attribute group.\n");
        goto sysfs_err;
    }

	/* setup misc char device */
    chip->tof_mdev.fops = &tof_miscdev_fops;
    chip->tof_mdev.name = "tof_tmf8829";
    chip->tof_mdev.minor = MISC_DYNAMIC_MINOR;
	error = misc_register(&chip->tof_mdev);

    if (error) {
        dev_err(&chip->client->dev, "Error registering misc_dev.\n");
        goto misc_reg_err;
    }

    dev_info(&chip->client->dev, "Probe pass.\n");

    AMS_MUTEX_UNLOCK(&chip->lock);

    return 0;

    /* Probe error handling */
misc_reg_err:
sysfs_err:
    sysfs_remove_groups(&chip->client->dev.kobj, tmf8829_attr_groups);
gen_err:
    AMS_MUTEX_UNLOCK(&chip->lock);
    if (chip->poll_period != 0) {
        (void)kthread_stop(chip->app_poll_irq);
    }
gpio_err:

    enablePinLow(chip);
    AMS_MUTEX_UNLOCK(&chip->lock);
    return error;
}

In this function, the first four instances of goto gpio_err; are prior to the first instance of AMS_MUTEX_LOCK(&chip->lock); which leads to a disallowed release of a non-locked mutex.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions