All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Barnabás Pőcze" <pobrn@protonmail.com>
To: Coiby Xu <coiby.xu@gmail.com>
Cc: "linux-input@vger.kernel.org" <linux-input@vger.kernel.org>,
	Helmut Stult <helmut.stult@schinfo.de>,
	"stable@vger.kernel.org" <stable@vger.kernel.org>,
	Jiri Kosina <jikos@kernel.org>,
	Benjamin Tissoires <benjamin.tissoires@redhat.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v3] HID: i2c-hid: add polling mode based on connected GPIO chip's pin status
Date: Thu, 22 Oct 2020 14:22:51 +0000	[thread overview]
Message-ID: <qo0Y8DqV6mbQsSFabOaqRoxYhKdYCZPjqYuF811CTdPXRFFXpx7sNXYcW9OGI5PMyclgsTjI7Xj3Du3v4hYQVBWGJl3t0t8XSbTKE9uOJ2E=@protonmail.com> (raw)
In-Reply-To: <20201021134931.462560-1-coiby.xu@gmail.com>

Hi,

I think this looks a lot better than the first version, the issues around
suspend/resume are sorted out as far as I can see. However, I still have a couple
comments, mainly minor ones.


> [...]
> +/* polling mode */
> +#define I2C_HID_POLLING_DISABLED 0
> +#define I2C_HID_POLLING_GPIO_PIN 1
> +#define I2C_HID_POLLING_INTERVAL_ACTIVE_US 4000
> +#define I2C_HID_POLLING_INTERVAL_IDLE_MS 10
> +
> +static u8 polling_mode;
> +module_param(polling_mode, byte, 0444);
> +MODULE_PARM_DESC(polling_mode, "How to poll - 0 disabled; 1 based on GPIO pin's status");
> +

Minor thing, but maybe the default value should be documented in the parameter
description?


> +static unsigned int polling_interval_active_us = I2C_HID_POLLING_INTERVAL_ACTIVE_US;
> +module_param(polling_interval_active_us, uint, 0644);
> +MODULE_PARM_DESC(polling_interval_active_us,
> +		 "Poll every {polling_interval_active_us} us when the touchpad is active. Default to 4000 us");
> +
> +static unsigned int polling_interval_idle_ms = I2C_HID_POLLING_INTERVAL_IDLE_MS;

Since these two parameters are mostly read, I think the `__read_mostly`
attribute (linux/cache.h) is justified here.


> +module_param(polling_interval_idle_ms, uint, 0644);
> +MODULE_PARM_DESC(polling_interval_idle_ms,
> +		 "Poll every {polling_interval_idle_ms} ms when the touchpad is idle. Default to 10 ms");

This is minor stylistic thing; as far as I see, the prevalent pattern is to put
the default value at the end, in parenthesis:
E.g. "some parameter description (default=X)" or "... (default: X)" or something similar

Maybe __stringify() (linux/stringify.h) could be used here and for the previous
module parameter?

E.g. "... (default=" __stringify(I2C_HID_POLLING_INTERVAL_IDLE_MS) ")"


> [...]
> +static int get_gpio_pin_state(struct irq_desc *irq_desc)
> +{
> +	struct gpio_chip *gc = irq_data_get_irq_chip_data(&irq_desc->irq_data);
> +
> +	return gc->get(gc, irq_desc->irq_data.hwirq);
> +}
> +
> +static bool interrupt_line_active(struct i2c_client *client)
> +{
> +	unsigned long trigger_type = irq_get_trigger_type(client->irq);

Can the trigger type change? Because if not, then I think it'd be better to store
the value somewhere and not query it every time.


> +	struct irq_desc *irq_desc = irq_to_desc(client->irq);

Same here.


> +	ssize_t	status = get_gpio_pin_state(irq_desc);

`get_gpio_pin_state()` returns an `int`, so I am not sure why `ssize_t` is used here.


> +
> +	if (status < 0) {
> +		dev_warn(&client->dev,
> +			 "Failed to get GPIO Interrupt line status for %s",
> +			 client->name);

I think it's possible that the kernel message buffer is flooded with these
messages, which is not optimal in my opinion.


> +		return false;
> +	}
> +	/*
> +	 * According to Windows Precsiontion Touchpad's specs
> +	 * https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-precision-touchpad-device-bus-connectivity,
> +	 * GPIO Interrupt Assertion Leve could be either ActiveLow or
> +	 * ActiveHigh.
> +	 */
> +	if (trigger_type & IRQF_TRIGGER_LOW)
> +		return !status;
> +
> +	return status;
> +}
> +
> +static int i2c_hid_polling_thread(void *i2c_hid)
> +{
> +	struct i2c_hid *ihid = i2c_hid;
> +	struct i2c_client *client = ihid->client;
> +	unsigned int polling_interval_idle;
> +
> +	while (1) {
> +		if (kthread_should_stop())
> +			break;

I think this should be `while (!kthread_should_stop())`.


> +
> +		while (interrupt_line_active(client) &&
> +		       !test_bit(I2C_HID_READ_PENDING, &ihid->flags) &&
> +		       !kthread_should_stop()) {
> +			i2c_hid_get_input(ihid);
> +			usleep_range(polling_interval_active_us,
> +				     polling_interval_active_us + 100);
> +		}
> +		/*
> +		 * re-calculate polling_interval_idle
> +		 * so the module parameters polling_interval_idle_ms can be
> +		 * changed dynamically through sysfs as polling_interval_active_us
> +		 */
> +		polling_interval_idle = polling_interval_idle_ms * 1000;
> +		usleep_range(polling_interval_idle,
> +			     polling_interval_idle + 1000);

I don't quite understand why you use an extra variable here. I'm assuming
you want to "save" a multiplication? I believe the compiler will optimize it
to a single read, and single multiplication regardless whether you use a "temporary"
variable or not.


> +	}
> +
> +	do_exit(0);

Looking at other examples, I don't think `do_exit()` is necessary.


> +	return 0;
> +}
> +
> +static int i2c_hid_init_polling(struct i2c_hid *ihid)
> +{
> +	struct i2c_client *client = ihid->client;
> +
> +	if (!irq_get_trigger_type(client->irq)) {
> +		dev_warn(&client->dev,
> +			 "Failed to get GPIO Interrupt Assertion Level, could not enable polling mode for %s",
> +			 client->name);
> +		return -EINVAL;
> +	}
> +
> +	ihid->polling_thread = kthread_create(i2c_hid_polling_thread, ihid,
> +					      "I2C HID polling thread");
> +
> +	if (!IS_ERR(ihid->polling_thread)) {
> +		pr_info("I2C HID polling thread created");
> +		wake_up_process(ihid->polling_thread);
> +		return 0;
> +	}
> +
> +	return PTR_ERR(ihid->polling_thread);

I would personally rewrite this parts as

```
if (IS_ERR(...)) {
  dev_err(...);
  return PTR_ERR(...);
}
....
return 0;
```


> +}
> [...]


Regards,
Barnabás Pőcze

  reply	other threads:[~2020-10-22 14:23 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-21 13:49 [PATCH v3] HID: i2c-hid: add polling mode based on connected GPIO chip's pin status Coiby Xu
2020-10-22 14:22 ` Barnabás Pőcze [this message]
2020-11-22 10:15   ` Coiby Xu
2020-11-22 13:33     ` Barnabás Pőcze
2020-11-23 14:36       ` Coiby Xu
2020-11-23 16:32         ` Barnabás Pőcze
2020-11-25 10:57           ` Coiby Xu
2020-11-25 12:39             ` Barnabás Pőcze
2020-11-25 13:18               ` Coiby Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='qo0Y8DqV6mbQsSFabOaqRoxYhKdYCZPjqYuF811CTdPXRFFXpx7sNXYcW9OGI5PMyclgsTjI7Xj3Du3v4hYQVBWGJl3t0t8XSbTKE9uOJ2E=@protonmail.com' \
    --to=pobrn@protonmail.com \
    --cc=benjamin.tissoires@redhat.com \
    --cc=coiby.xu@gmail.com \
    --cc=helmut.stult@schinfo.de \
    --cc=jikos@kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.