Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d32e5f44 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull input fixes from Dmitry Torokhov:

 - fixes for two long standing issues (lock up and a crash) in force
   feedback handling in uinput driver

 - tweak to firmware update timing in Elan I2C touchpad driver.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: elan_i2c - extend Flash-Write delay
  Input: uinput - avoid crash when sending FF request to device going away
  Input: uinput - avoid FF flush when destroying device
parents c0a3a64e 05f5c385
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -237,9 +237,15 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file)
EXPORT_SYMBOL_GPL(input_ff_erase);

/*
 * flush_effects - erase all effects owned by a file handle
 * input_ff_flush - erase all effects owned by a file handle
 * @dev: input device to erase effect from
 * @file: purported owner of the effects
 *
 * This function erases all force-feedback effects associated with
 * the given owner from specified device. Note that @file may be %NULL,
 * in which case all effects will be erased.
 */
static int flush_effects(struct input_dev *dev, struct file *file)
int input_ff_flush(struct input_dev *dev, struct file *file)
{
	struct ff_device *ff = dev->ff;
	int i;
@@ -255,6 +261,7 @@ static int flush_effects(struct input_dev *dev, struct file *file)

	return 0;
}
EXPORT_SYMBOL_GPL(input_ff_flush);

/**
 * input_ff_event() - generic handler for force-feedback events
@@ -343,7 +350,7 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
	mutex_init(&ff->mutex);

	dev->ff = ff;
	dev->flush = flush_effects;
	dev->flush = input_ff_flush;
	dev->event = input_ff_event;
	__set_bit(EV_FF, dev->evbit);

+39 −18
Original line number Diff line number Diff line
@@ -98,14 +98,15 @@ static int uinput_request_reserve_slot(struct uinput_device *udev,
					uinput_request_alloc_id(udev, request));
}

static void uinput_request_done(struct uinput_device *udev,
				struct uinput_request *request)
static void uinput_request_release_slot(struct uinput_device *udev,
					unsigned int id)
{
	/* Mark slot as available */
	udev->requests[request->id] = NULL;
	wake_up(&udev->requests_waitq);
	spin_lock(&udev->requests_lock);
	udev->requests[id] = NULL;
	spin_unlock(&udev->requests_lock);

	complete(&request->done);
	wake_up(&udev->requests_waitq);
}

static int uinput_request_send(struct uinput_device *udev,
@@ -138,20 +139,22 @@ static int uinput_request_send(struct uinput_device *udev,
static int uinput_request_submit(struct uinput_device *udev,
				 struct uinput_request *request)
{
	int error;
	int retval;

	error = uinput_request_reserve_slot(udev, request);
	if (error)
		return error;
	retval = uinput_request_reserve_slot(udev, request);
	if (retval)
		return retval;

	error = uinput_request_send(udev, request);
	if (error) {
		uinput_request_done(udev, request);
		return error;
	}
	retval = uinput_request_send(udev, request);
	if (retval)
		goto out;

	wait_for_completion(&request->done);
	return request->retval;
	retval = request->retval;

 out:
	uinput_request_release_slot(udev, request->id);
	return retval;
}

/*
@@ -169,7 +172,7 @@ static void uinput_flush_requests(struct uinput_device *udev)
		request = udev->requests[i];
		if (request) {
			request->retval = -ENODEV;
			uinput_request_done(udev, request);
			complete(&request->done);
		}
	}

@@ -230,6 +233,18 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
	return uinput_request_submit(udev, &request);
}

static int uinput_dev_flush(struct input_dev *dev, struct file *file)
{
	/*
	 * If we are called with file == NULL that means we are tearing
	 * down the device, and therefore we can not handle FF erase
	 * requests: either we are handling UI_DEV_DESTROY (and holding
	 * the udev->mutex), or the file descriptor is closed and there is
	 * nobody on the other side anymore.
	 */
	return file ? input_ff_flush(dev, file) : 0;
}

static void uinput_destroy_device(struct uinput_device *udev)
{
	const char *name, *phys;
@@ -297,6 +312,12 @@ static int uinput_create_device(struct uinput_device *udev)
		dev->ff->playback = uinput_dev_playback;
		dev->ff->set_gain = uinput_dev_set_gain;
		dev->ff->set_autocenter = uinput_dev_set_autocenter;
		/*
		 * The standard input_ff_flush() implementation does
		 * not quite work for uinput as we can't reasonably
		 * handle FF requests during device teardown.
		 */
		dev->flush = uinput_dev_flush;
	}

	error = input_register_device(udev->dev);
@@ -939,7 +960,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
			}

			req->retval = ff_up.retval;
			uinput_request_done(udev, req);
			complete(&req->done);
			goto out;

		case UI_END_FF_ERASE:
@@ -955,7 +976,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
			}

			req->retval = ff_erase.retval;
			uinput_request_done(udev, req);
			complete(&req->done);
			goto out;
	}

+1 −1
Original line number Diff line number Diff line
@@ -598,7 +598,7 @@ static int elan_i2c_write_fw_block(struct i2c_client *client,
	}

	/* Wait for F/W to update one page ROM data. */
	msleep(20);
	msleep(35);

	error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val);
	if (error) {
+1 −0
Original line number Diff line number Diff line
@@ -529,6 +529,7 @@ int input_ff_event(struct input_dev *dev, unsigned int type, unsigned int code,

int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, struct file *file);
int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
int input_ff_flush(struct input_dev *dev, struct file *file);

int input_ff_create_memless(struct input_dev *dev, void *data,
		int (*play_effect)(struct input_dev *, void *, struct ff_effect *));