static int test_abba(bool resolve) { struct test_abba abba; struct ww_acquire_ctx ctx; int err, ret; ww_mutex_init(&abba.a_mutex, &ww_class); ww_mutex_init(&abba.b_mutex, &ww_class); INIT_WORK_ONSTACK(&abba.work, test_abba_work); init_completion(&abba.a_ready); init_completion(&abba.b_ready); abba.resolve = resolve; schedule_work(&abba.work); ww_acquire_init(&ctx, &ww_class); ww_mutex_lock(&abba.a_mutex, &ctx); complete(&abba.a_ready); wait_for_completion(&abba.b_ready); err = ww_mutex_lock(&abba.b_mutex, &ctx); if (resolve && err == -EDEADLK) { ww_mutex_unlock(&abba.a_mutex); ww_mutex_lock_slow(&abba.b_mutex, &ctx); err = ww_mutex_lock(&abba.a_mutex, &ctx); } if (!err) ww_mutex_unlock(&abba.b_mutex); ww_mutex_unlock(&abba.a_mutex); ww_acquire_fini(&ctx); flush_work(&abba.work); destroy_work_on_stack(&abba.work); ret = 0; if (resolve) { if (err || abba.result) { pr_err("%s: failed to resolve ABBA deadlock, A err=%d, B err=%d\n", __func__, err, abba.result); ret = -EINVAL; } } else { if (err != -EDEADLK && abba.result != -EDEADLK) { pr_err("%s: missed ABBA deadlock, A err=%d, B err=%d\n", __func__, err, abba.result); ret = -EINVAL; } } return ret; }
static int max77660_haptic_remove(struct platform_device *pdev) { struct max77660_haptic *chip = platform_get_drvdata(pdev); destroy_work_on_stack(&chip->work); input_unregister_device(chip->input_dev); sysfs_remove_group(&pdev->dev.kobj, &max77660_haptics_attr_group); regulator_put(chip->regulator); if (chip->mode == MAX77660_EXTERNAL_MODE) pwm_free(chip->pwm); return 0; }
static int __test_mutex(unsigned int flags) { #define TIMEOUT (HZ / 16) struct test_mutex mtx; struct ww_acquire_ctx ctx; int ret; ww_mutex_init(&mtx.mutex, &ww_class); ww_acquire_init(&ctx, &ww_class); INIT_WORK_ONSTACK(&mtx.work, test_mutex_work); init_completion(&mtx.ready); init_completion(&mtx.go); init_completion(&mtx.done); mtx.flags = flags; schedule_work(&mtx.work); wait_for_completion(&mtx.ready); ww_mutex_lock(&mtx.mutex, (flags & TEST_MTX_CTX) ? &ctx : NULL); complete(&mtx.go); if (flags & TEST_MTX_SPIN) { unsigned long timeout = jiffies + TIMEOUT; ret = 0; do { if (completion_done(&mtx.done)) { ret = -EINVAL; break; } cond_resched(); } while (time_before(jiffies, timeout)); } else { ret = wait_for_completion_timeout(&mtx.done, TIMEOUT); } ww_mutex_unlock(&mtx.mutex); ww_acquire_fini(&ctx); if (ret) { pr_err("%s(flags=%x): mutual exclusion failure\n", __func__, flags); ret = -EINVAL; } flush_work(&mtx.work); destroy_work_on_stack(&mtx.work); return ret; #undef TIMEOUT }
/* * Some allocation requests often come in with little stack to work on. Push * them off to a worker thread so there is lots of stack to use. Otherwise just * call directly to avoid the context switch overhead here. */ int xfs_bmapi_allocate( struct xfs_bmalloca *args) { DECLARE_COMPLETION_ONSTACK(done); if (!args->stack_switch) return __xfs_bmapi_allocate(args); args->done = &done; INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker); queue_work(xfs_alloc_wq, &args->work); wait_for_completion(&done); destroy_work_on_stack(&args->work); return args->result; }
static int max77660_haptic_probe(struct platform_device *pdev) { /* we register the parent platform data */ struct max77660_platform_data *parent_pdata; struct max77660_haptic_platform_data *haptic_pdata; struct max77660_haptic *chip; struct input_dev *input_dev; int ret; parent_pdata = dev_get_platdata(pdev->dev.parent); if (!parent_pdata) { dev_err(&pdev->dev, "no haptic parent platform data\n"); return -EINVAL; } if ((!parent_pdata->haptic_pdata) || !parent_pdata->haptic_pdata->pdata) { dev_err(&pdev->dev, "no haptic platform data\n"); return -EINVAL; } haptic_pdata = parent_pdata->haptic_pdata->pdata; chip = devm_kzalloc(&pdev->dev, sizeof(struct max77660_haptic), GFP_KERNEL); if (!chip) { dev_err(&pdev->dev, "unable to allocate memory\n"); return -ENOMEM; } input_dev = input_allocate_device(); if (!input_dev) { dev_err(&pdev->dev, "unable to allocate memory for input dev\n"); ret = -ENOMEM; goto err_input_alloc; } chip->dev = &pdev->dev; chip->input_dev = input_dev; chip->type = haptic_pdata->type; chip->mode = haptic_pdata->mode; if (chip->mode == MAX77660_INTERNAL_MODE) { chip->internal_mode_pattern = haptic_pdata->internal_mode_pattern; chip->pattern_cycle = haptic_pdata->pattern_cycle; chip->pattern_signal_period = haptic_pdata->pattern_signal_period; chip->feedback_duty_cycle = haptic_pdata->feedback_duty_cycle; chip->invert = haptic_pdata->invert; chip->cont_mode = haptic_pdata->cont_mode; chip->motor_startup_val = haptic_pdata->motor_startup_val; chip->scf_val = haptic_pdata->scf_val; } if (chip->mode == MAX77660_EXTERNAL_MODE) { chip->pwm = pwm_request(haptic_pdata->pwm_channel_id, "max-vbrtr"); if (IS_ERR(chip->pwm)) { dev_err(&pdev->dev, "unable to request PWM for haptic\n"); ret = PTR_ERR(chip->pwm); goto err_pwm; } } chip->regulator = regulator_get(&pdev->dev, "vdd_vbrtr"); if (IS_ERR(chip->regulator)) { dev_err(&pdev->dev, "unable to get regulator\n"); ret = PTR_ERR(chip->regulator); goto err_regulator; } register_input: dev_set_drvdata(&pdev->dev, chip); input_dev->name = MAX77660_HAPTIC_DRIVER_MATCHED_NAME; input_dev->id.version = 1; input_dev->dev.parent = &pdev->dev; input_set_drvdata(input_dev, chip); input_set_capability(input_dev, EV_FF, FF_RUMBLE); ret = input_ff_create_memless(input_dev, NULL, max77660_haptic_play_effect); if (ret) { dev_err(&pdev->dev, "unable to create FF device(ret : %d)\n", ret); goto err_ff_memless; } INIT_WORK(&chip->work, max77660_haptic_play_effect_work); ret = input_register_device(input_dev); if (ret) { dev_err(&pdev->dev, "unable to register input device(ret : %d)\n", ret); goto err_input_register; } ret = sysfs_create_group(&pdev->dev.kobj, &max77660_haptics_attr_group); if (ret < 0) dev_err(&pdev->dev, "unable to create sysfs %d\n", ret); return 0; err_input_register: destroy_work_on_stack(&chip->work); input_ff_destroy(input_dev); err_ff_memless: regulator_put(chip->regulator); err_regulator: if (chip->mode == MAX77660_EXTERNAL_MODE) pwm_free(chip->pwm); err_pwm: input_free_device(input_dev); err_input_alloc: dev_err(&pdev->dev, "Error: %s return ret=%d\n", __func__, ret); return ret; }
static int __devinit max77665_haptic_probe(struct platform_device *pdev) { struct max77665_haptic_platform_data *haptic_pdata = pdev->dev.platform_data; struct max77665_haptic *chip; struct edp_manager *battery_manager = NULL; struct input_dev *input_dev; int ret; if (!haptic_pdata) { dev_err(&pdev->dev, "no haptic platform data\n"); return -EINVAL; } chip = devm_kzalloc(&pdev->dev, sizeof(struct max77665_haptic), GFP_KERNEL); if (!chip) { dev_err(&pdev->dev, "unable to allocate memory\n"); return -ENOMEM; } input_dev = input_allocate_device(); if (!input_dev) { dev_err(&pdev->dev, "unable to allocate memory for input dev\n"); ret = -ENOMEM; goto err_input_alloc; } chip->dev = &pdev->dev; chip->input_dev = input_dev; chip->pwm_period = haptic_pdata->pwm_period; chip->type = haptic_pdata->type; chip->mode = haptic_pdata->mode; chip->pwm_divisor = haptic_pdata->pwm_divisor; if (chip->mode == MAX77665_INTERNAL_MODE) { chip->internal_mode_pattern = haptic_pdata->internal_mode_pattern; chip->pattern_cycle = haptic_pdata->pattern_cycle; chip->pattern_signal_period = haptic_pdata->pattern_signal_period; chip->feedback_duty_cycle = haptic_pdata->feedback_duty_cycle; chip->invert = haptic_pdata->invert; chip->cont_mode = haptic_pdata->cont_mode; chip->motor_startup_val = haptic_pdata->motor_startup_val; chip->scf_val = haptic_pdata->scf_val; } if (chip->mode == MAX77665_EXTERNAL_MODE) { chip->pwm = pwm_request(haptic_pdata->pwm_channel_id, "max-vbrtr"); if (IS_ERR(chip->pwm)) { dev_err(&pdev->dev, "unable to request PWM for haptic\n"); ret = PTR_ERR(chip->pwm); goto err_pwm; } } chip->regulator = regulator_get(&pdev->dev, "vdd_vbrtr"); if (IS_ERR(chip->regulator)) { dev_err(&pdev->dev, "unable to get regulator\n"); ret = PTR_ERR(chip->regulator); goto err_regulator; } if (haptic_pdata->edp_states == NULL) goto register_input; chip->haptic_edp_client = devm_kzalloc(&pdev->dev, sizeof(struct edp_client), GFP_KERNEL); if (IS_ERR_OR_NULL(chip->haptic_edp_client)) { dev_err(&pdev->dev, "could not allocate edp client\n"); goto register_input; } chip->haptic_edp_client->name[EDP_NAME_LEN - 1] = '\0'; strncpy(chip->haptic_edp_client->name, "vibrator", EDP_NAME_LEN - 1); chip->haptic_edp_client->states = haptic_pdata->edp_states; chip->haptic_edp_client->num_states = MAX77665_HAPTIC_EDP_NUM_STATES; chip->haptic_edp_client->e0_index = MAX77665_HAPTIC_EDP_LOW; chip->haptic_edp_client->priority = EDP_MAX_PRIO + 2; chip->haptic_edp_client->throttle = max77665_haptic_throttle; chip->haptic_edp_client->private_data = chip; battery_manager = edp_get_manager("battery"); if (!battery_manager) { dev_err(&pdev->dev, "unable to get edp manager\n"); } else { ret = edp_register_client(battery_manager, chip->haptic_edp_client); if (ret) { dev_err(&pdev->dev, "unable to register edp client\n"); } else { ret = edp_update_client_request(chip->haptic_edp_client, MAX77665_HAPTIC_EDP_LOW, NULL); if (ret) { dev_err(&pdev->dev, "unable to set E0 EDP state\n"); edp_unregister_client(chip->haptic_edp_client); } else { goto register_input; } } } devm_kfree(&pdev->dev, chip->haptic_edp_client); chip->haptic_edp_client = NULL; register_input: dev_set_drvdata(&pdev->dev, chip); input_dev->name = "max77665-haptic"; input_dev->id.version = 1; input_dev->dev.parent = &pdev->dev; input_set_drvdata(input_dev, chip); input_set_capability(input_dev, EV_FF, FF_RUMBLE); ret = input_ff_create_memless(input_dev, NULL, max77665_haptic_play_effect); if (ret) { dev_err(&pdev->dev, "unable to create FF device(ret : %d)\n", ret); goto err_ff_memless; } INIT_WORK(&chip->work, max77665_haptic_play_effect_work); ret = input_register_device(input_dev); if (ret) { dev_err(&pdev->dev, "unable to register input device(ret : %d)\n", ret); goto err_input_register; } ret = sysfs_create_group(&pdev->dev.kobj, &max77665_haptics_attr_group); if (ret < 0) { dev_err(&pdev->dev, "unable to create sysfs %d\n", ret); } return 0; err_input_register: destroy_work_on_stack(&chip->work); input_ff_destroy(input_dev); err_ff_memless: regulator_put(chip->regulator); err_regulator: if (chip->mode == MAX77665_EXTERNAL_MODE) pwm_free(chip->pwm); err_pwm: input_free_device(input_dev); err_input_alloc: kfree(chip); return ret; }