All of lore.kernel.org
 help / color / mirror / Atom feed
From: Coiby Xu <coiby.xu@gmail.com>
To: "Barnabás Pőcze" <pobrn@protonmail.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: Sun, 22 Nov 2020 18:15:25 +0800	[thread overview]
Message-ID: <20201122101525.j265hvj6lqgbtfi2@Rk> (raw)
In-Reply-To: <qo0Y8DqV6mbQsSFabOaqRoxYhKdYCZPjqYuF811CTdPXRFFXpx7sNXYcW9OGI5PMyclgsTjI7Xj3Du3v4hYQVBWGJl3t0t8XSbTKE9uOJ2E=@protonmail.com>

Hi,

On Thu, Oct 22, 2020 at 02:22:51PM +0000, Barnabás Pőcze wrote:
>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.
>
Thank you for reviewing this patch!
>
>> [...]
>> +/* 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) ")"
>
Thank you for the above three suggestions! Will be applied in v4.
>
>> [...]
>> +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.
>
The irq trigger type is obtained from ACPI so I don't think it won't
change.
>
>> +	struct irq_desc *irq_desc = irq_to_desc(client->irq);
>
>Same here.
>
Thank you for the reminding!
>
>> +	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.
>

I used `ssize_t` because I found gpiolib-sysfs.c uses `ssize_t`

     // drivers/gpio/gpiolib-sysfs.c
     static ssize_t value_show(struct device *dev,
     		struct device_attribute *attr, char *buf)
     {
     	struct gpiod_data *data = dev_get_drvdata(dev);
     	struct gpio_desc *desc = data->desc;
     	ssize_t			status;

     	mutex_lock(&data->mutex);

     	status = gpiod_get_value_cansleep(desc);
         ...
     	return status;
     }

According to the book Advanced Programming in the UNIX Environment by
W. Richard Stevens,
     With the 1990 POSIX.1 standard, the primitive system data type
     ssize_t was introduced to provide the signed return value...

So ssize_t is fairly common, for example, the read and write syscall
return a value of type ssize_t. But I haven't found out why ssize_t is
better int.
>
>> +
>> +	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.
>
Thank you! Replaced with dev_dbg in v4.
>
>> +		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())`.
>
This simplifies the code. Thank you!
>
>> +
>> +		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.
>
According to the doc of kthread_create_on_node,
     @threadfn() can either call do_exit() directly if it is a
     * standalone thread for which no one will call kthread_stop(), or
     * return when 'kthread_should_stop()' is true (which means
     * kthread_stop() has been called).

do_exit is not necessary. Thank you for raising up this issue and
looking at other examples for me!
>
>> +	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;
>```

Thank you! This style is consistent with other functions in this file.
>
>
>> +}
>> [...]
>
>
>Regards,
>Barnabás Pőcze

--
Best regards,
Coiby

  reply	other threads:[~2020-11-22 10:16 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
2020-11-22 10:15   ` Coiby Xu [this message]
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=20201122101525.j265hvj6lqgbtfi2@Rk \
    --to=coiby.xu@gmail.com \
    --cc=benjamin.tissoires@redhat.com \
    --cc=helmut.stult@schinfo.de \
    --cc=jikos@kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pobrn@protonmail.com \
    --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.