From: Greg KH <gregkh@linuxfoundation.org>
To: Wentong Wu <wentong.wu@intel.com>
Cc: arnd@arndb.de, mka@chromium.org, oneukum@suse.com,
lee@kernel.org, wsa@kernel.org, kfting@nuvoton.com,
broonie@kernel.org, linus.walleij@linaro.org,
hdegoede@redhat.com, maz@kernel.org, brgl@bgdev.pl,
linux-usb@vger.kernel.org, linux-i2c@vger.kernel.org,
linux-spi@vger.kernel.org, linux-gpio@vger.kernel.org,
andriy.shevchenko@linux.intel.com,
heikki.krogerus@linux.intel.com, andi.shyti@linux.intel.com,
sakari.ailus@linux.intel.com, bartosz.golaszewski@linaro.org,
srinivas.pandruvada@intel.com, zhifeng.wang@intel.com
Subject: Re: [PATCH v15 1/4] usb: Add support for Intel LJCA device
Date: Fri, 8 Sep 2023 14:38:31 +0100 [thread overview]
Message-ID: <2023090854-verse-crabmeat-bf14@gregkh> (raw)
In-Reply-To: <1693970580-18967-2-git-send-email-wentong.wu@intel.com>
On Wed, Sep 06, 2023 at 11:22:57AM +0800, Wentong Wu wrote:
> +struct ljca_bank_descriptor {
> + u8 bank_id;
> + u8 pin_num;
> +
> + /* 1 bit for each gpio, 1 means valid */
> + u32 valid_pins;
> +} __packed;
This is an unaligned access, do you mean to have that?
> +struct ljca_adapter {
> + struct usb_interface *intf;
> + struct usb_device *usb_dev;
> + struct device *dev;
> +
> + unsigned int rx_pipe;
> + unsigned int tx_pipe;
> +
> + /* urb for recv */
> + struct urb *rx_urb;
> + /* buffer for recv */
> + void *rx_buf;
> + unsigned int rx_len;
> +
> + /* external buffer for recv */
> + void *ex_buf;
Shouldn't buffers be u8*?
> +static void ljca_handle_event(struct ljca_adapter *adap,
> + struct ljca_msg *header)
> +{
> + struct ljca_client *client;
> +
> + list_for_each_entry(client, &adap->client_list, link) {
> + /*
> + * FIXME: currently only GPIO register event callback.
When is this fixme going to be addressed?
> + * firmware message structure should include id when
> + * multiple same type clients register event callback.
> + */
> + if (client->type == header->type) {
> + unsigned long flags;
> +
> + spin_lock_irqsave(&client->event_cb_lock, flags);
> + client->event_cb(client->context, header->cmd,
> + header->data, header->len);
> + spin_unlock_irqrestore(&client->event_cb_lock, flags);
> +
> + break;
> + }
> + }
> +}
> +
> +/* process command ack */
> +static void ljca_handle_cmd_ack(struct ljca_adapter *adap,
> + struct ljca_msg *header)
> +{
> + struct ljca_msg *tx_header = adap->tx_buf;
> + unsigned int actual_len = 0;
> + unsigned int ibuf_len;
> + unsigned long flags;
> + void *ibuf;
> +
> + spin_lock_irqsave(&adap->lock, flags);
Why not use the functionality in cleanup.h for this lock? Makes this
function much simpler.
> +
> + if (tx_header->type != header->type || tx_header->cmd != header->cmd) {
> + spin_unlock_irqrestore(&adap->lock, flags);
> +
No need for a blank line.
And how can these things happen? No need to return an error if this is
the case?
> +static int ljca_send(struct ljca_adapter *adap, u8 type, u8 cmd,
> + const void *obuf, unsigned int obuf_len, void *ibuf,
> + unsigned int ibuf_len, bool ack, unsigned long timeout)
That's a lot of function parameters, whyh so many?
And why void *? That should never be used in an internal function where
you know the real type.
> +{
> + unsigned int msg_len = sizeof(struct ljca_msg) + obuf_len;
> + struct ljca_msg *header = adap->tx_buf;
> + unsigned long flags;
> + unsigned int actual;
> + int ret = 0;
> +
> + if (adap->disconnect)
> + return -ENODEV;
> +
> + if (msg_len > adap->tx_buf_len)
> + return -EINVAL;
> +
> + mutex_lock(&adap->mutex);
> +
> + spin_lock_irqsave(&adap->lock, flags);
2 locks? Why 2 locks for the same structure?
> +
> + header->type = type;
> + header->cmd = cmd;
> + header->len = obuf_len;
> + if (obuf)
> + memcpy(header->data, obuf, obuf_len);
> +
> + header->flags = LJCA_CMPL_FLAG | (ack ? LJCA_ACK_FLAG : 0);
> +
> + adap->ex_buf = ibuf;
> + adap->ex_buf_len = ibuf_len;
> + adap->actual_length = 0;
> +
> + spin_unlock_irqrestore(&adap->lock, flags);
> +
> + reinit_completion(&adap->cmd_completion);
> +
> + usb_autopm_get_interface(adap->intf);
> +
> + ret = usb_bulk_msg(adap->usb_dev, adap->tx_pipe, header,
> + msg_len, &actual, LJCA_WRITE_TIMEOUT_MS);
This function is slow. Really slow. You drop the spinlock which is
good, but the mutex is still held. Does this call have to be
synchronous?
> +
> + usb_autopm_put_interface(adap->intf);
> +
> + if (!ret && ack) {
> + ret = wait_for_completion_timeout(&adap->cmd_completion,
> + timeout);
> + if (ret < 0) {
> + goto out;
> + } if (!ret) {
> + ret = -ETIMEDOUT;
> + goto out;
> + }
> + }
> + ret = adap->actual_length;
> +
> +out:
> + spin_lock_irqsave(&adap->lock, flags);
> + adap->ex_buf = NULL;
> + adap->ex_buf_len = 0;
> +
> + memset(header, 0, sizeof(*header));
Why?
> + spin_unlock_irqrestore(&adap->lock, flags);
> +
> + mutex_unlock(&adap->mutex);
> +
> + return ret;
> +}
> +
> +int ljca_transfer(struct ljca_client *client, u8 cmd, const void *obuf,
Again, drop all void * please, use real types in your apis.
> +#else
> +static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap,
> + struct auxiliary_device *auxdev,
> + u64 adr, u8 id)
> +{
> +}
> +#endif
Can't this go in a .h file? #ifdef in .c files are frowned apon.
> +static int ljca_enumerate_clients(struct ljca_adapter *adap)
> +{
> + int ret;
> +
> + ret = ljca_reset_handshake(adap);
> + if (ret)
> + return ret;
> +
> + ret = ljca_enumerate_gpio(adap);
> + if (ret)
> + dev_warn(adap->dev, "enumerate GPIO error\n");
> +
> + ret = ljca_enumerate_i2c(adap);
> + if (ret)
> + dev_warn(adap->dev, "enumerate I2C error\n");
> +
> + ret = ljca_enumerate_spi(adap);
> + if (ret)
> + dev_warn(adap->dev, "enumerate SPI error\n");
You warn about these things, but keep on saying the code is working
properly with a return of:
> + return 0;
That's not good. Why not unwind properly and handle the error?
> --- /dev/null
> +++ b/include/linux/usb/ljca.h
> @@ -0,0 +1,113 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2023, Intel Corporation. All rights reserved.
> + */
> +#ifndef _LINUX_USB_LJCA_H_
> +#define _LINUX_USB_LJCA_H_
> +
> +#include <linux/auxiliary_bus.h>
> +#include <linux/list.h>
> +#include <linux/spinlock.h>
> +#include <linux/types.h>
> +
> +#define LJCA_MAX_GPIO_NUM 64
> +
> +#define auxiliary_dev_to_ljca_client(auxiliary_dev) \
> + container_of(auxiliary_dev, struct ljca_client, auxdev)
> +
> +struct ljca_adapter;
> +
> +/**
> + * typedef ljca_event_cb_t - event callback function signature
> + *
> + * @context: the execution context of who registered this callback
> + * @cmd: the command from device for this event
> + * @evt_data: the event data payload
> + * @len: the event data payload length
> + *
> + * The callback function is called in interrupt context and the data payload is
> + * only valid during the call. If the user needs later access of the data, it
> + * must copy it.
> + */
> +typedef void (*ljca_event_cb_t)(void *context, u8 cmd, const void *evt_data, int len);
> +
> +struct ljca_client {
> + u8 type;
> + u8 id;
> + struct list_head link;
> + struct auxiliary_device auxdev;
> + struct ljca_adapter *adapter;
> +
> + void *context;
> + ljca_event_cb_t event_cb;
> + /* lock to protect event_cb */
> + spinlock_t event_cb_lock;
> +};
> +
> +struct ljca_gpio_info {
> + unsigned int num;
> + DECLARE_BITMAP(valid_pin_map, LJCA_MAX_GPIO_NUM);
> +};
> +
> +struct ljca_i2c_info {
> + u8 id;
> + u8 capacity;
> + u8 intr_pin;
> +};
> +
> +struct ljca_spi_info {
> + u8 id;
> + u8 capacity;
> +};
No documentation for these other public structures?
thanks,
greg k-h
next prev parent reply other threads:[~2023-09-08 13:38 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-06 3:22 [PATCH v15 0/4] Add Intel LJCA device driver Wentong Wu
2023-09-06 3:22 ` [PATCH v15 1/4] usb: Add support for Intel LJCA device Wentong Wu
2023-09-08 13:38 ` Greg KH [this message]
2023-09-08 16:03 ` Wu, Wentong
2023-09-12 3:49 ` Wu, Wentong
2023-09-06 3:22 ` [PATCH v15 2/4] i2c: Add support for Intel LJCA USB I2C driver Wentong Wu
2023-09-06 3:22 ` [PATCH v15 3/4] spi: Add support for Intel LJCA USB SPI driver Wentong Wu
2023-09-06 3:23 ` [PATCH v15 4/4] gpio: update Intel LJCA USB GPIO driver Wentong Wu
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=2023090854-verse-crabmeat-bf14@gregkh \
--to=gregkh@linuxfoundation.org \
--cc=andi.shyti@linux.intel.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=arnd@arndb.de \
--cc=bartosz.golaszewski@linaro.org \
--cc=brgl@bgdev.pl \
--cc=broonie@kernel.org \
--cc=hdegoede@redhat.com \
--cc=heikki.krogerus@linux.intel.com \
--cc=kfting@nuvoton.com \
--cc=lee@kernel.org \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=maz@kernel.org \
--cc=mka@chromium.org \
--cc=oneukum@suse.com \
--cc=sakari.ailus@linux.intel.com \
--cc=srinivas.pandruvada@intel.com \
--cc=wentong.wu@intel.com \
--cc=wsa@kernel.org \
--cc=zhifeng.wang@intel.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).