[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAOoeyxU5nM4BZhgqcRxVHVVDxzLFzVS0+z7Yi_YGpvWc87mAbQ@mail.gmail.com>
Date: Mon, 30 Dec 2024 14:32:03 +0800
From: Ming Yu <a0282524688@...il.com>
To: Vincent Mailhol <mailhol.vincent@...adoo.fr>
Cc: linux-kernel@...r.kernel.org, linux-gpio@...r.kernel.org,
linux-i2c@...r.kernel.org, linux-can@...r.kernel.org, netdev@...r.kernel.org,
linux-watchdog@...r.kernel.org, linux-hwmon@...r.kernel.org,
linux-rtc@...r.kernel.org, tmyu0@...oton.com, lee@...nel.org,
linus.walleij@...aro.org, brgl@...ev.pl, andi.shyti@...nel.org,
mkl@...gutronix.de, andrew+netdev@...n.ch, davem@...emloft.net,
edumazet@...gle.com, kuba@...nel.org, pabeni@...hat.com,
wim@...ux-watchdog.org, linux@...ck-us.net, jdelvare@...e.com,
alexandre.belloni@...tlin.com, linux-usb@...r.kernel.org
Subject: Re: [PATCH v4 1/7] mfd: Add core driver for Nuvoton NCT6694
Dear Vincent,
Thank you for your comments,
Vincent Mailhol <mailhol.vincent@...adoo.fr> 於 2024年12月27日 週五 下午11:34寫道:
>
> +cc: linux-usb@...r.kernel.org
>
...
> > +config MFD_NCT6694
> > + tristate "Nuvoton NCT6694 support"
> > + select MFD_CORE
> > + depends on USB
> > + help
> > + This adds support for Nuvoton USB device NCT6694 sharing peripherals
> > + This includes the USB devcie driver and core APIs.
> ^^^^^^
> device
>
Fix it in v5.
> > + Additional drivers must be enabled in order to use the functionality
> > + of the device.
> > +
> > config MFD_HI6421_PMIC
> > tristate "HiSilicon Hi6421 PMU/Codec IC"
> > depends on OF
> > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> > index e057d6d6faef..9d0365ba6a26 100644
> > --- a/drivers/mfd/Makefile
> > +++ b/drivers/mfd/Makefile
> > @@ -117,6 +117,8 @@ obj-$(CONFIG_TWL6040_CORE) += twl6040.o
> >
> > obj-$(CONFIG_MFD_MX25_TSADC) += fsl-imx25-tsadc.o
> >
> > +obj-$(CONFIG_MFD_NCT6694) += nct6694.o
>
> Keep the alphabetic order. MFD_NCT6694 is after MFD_MC13XXX in the alphabet.
>
Fix it in v5.
> > obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
> > obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o
> > obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
> > diff --git a/drivers/mfd/nct6694.c b/drivers/mfd/nct6694.c
> > new file mode 100644
> > index 000000000000..0f31489ef9fa
> > --- /dev/null
> > +++ b/drivers/mfd/nct6694.c
>
> If I understand correctly, your device is an USB device, so shouldn't it
> be under
>
> drivers/usb/mfd/nct6694.c
>
> ?
I understand, but there is no drivers/usb/mfd/ directory, I believe my
device is similar to dln2.c and viperboard.c, which is why I placed it
under drivers/mfd/
>
> At the moment, I see no USB maintainers in CC (this is why I added
> linux-usb myself). By putting it in the correct folder, the
> get_maintainers.pl will give you the correct list of persons to put in copy.
>
Okay, I will add CC to linux-usb from now on.
> The same comment applies to the other modules. For example, I would
> expect to see the CAN module under:
>
> drivers/net/can/usb/nct6694_canfd.c
>
Understood! I will move the can driver to drivers/net/can/usb/ in v5.
...
> > +static int nct6694_response_err_handling(struct nct6694 *nct6694,
> > + unsigned char err_status)
> > +{
> > + struct device *dev = &nct6694->udev->dev;
> > +
> > + switch (err_status) {
> > + case NCT6694_NO_ERROR:
> > + return err_status;
> > + case NCT6694_NOT_SUPPORT_ERROR:
> > + dev_dbg(dev, "%s: Command is not support!\n", __func__);
>
> Grammar: Command is not supported
>
Fix it in v5.
> > + break;
> > + case NCT6694_NO_RESPONSE_ERROR:
> > + dev_dbg(dev, "%s: Command is no response!\n", __func__);
>
> Not sure what you meant here. Maybe: command didn't get a response? But
> then, I do not see the nuance with the timeout.
>
The firmware engine returns an error response.
If it returns NO_RESPONSE_ERROR, it means the target device did not
respond(e.g., I2C slave NACK).
If it returns TIMEOUT_ERROR, it means the engine process the command timed out.
I will add the comments to describe these error status in v5.
> > + break;
> > + case NCT6694_TIMEOUT_ERROR:
> > + dev_dbg(dev, "%s: Command is timeout!\n", __func__);
>
> Grammar: Command timed out
Fix it in v5.
> > + break;
> > + case NCT6694_PENDING:
> > + dev_dbg(dev, "%s: Command is pending!\n", __func__);
> > + break;> + default:
> > + return -EINVAL;
> > + }
> > +
> > + return -EIO;
> > +}
> > +
> > +int nct6694_read_msg(struct nct6694 *nct6694, u8 mod, u16 offset,
> > + u16 length, void *buf)
> > +{
> > + union nct6694_usb_msg *msg = nct6694->usb_msg;
> > + int tx_len, rx_len, ret;
> > +
> > + guard(mutex)(&nct6694->access_lock);
> > +
> > + memset(msg, 0, sizeof(*msg));
> > +
> > + /* Send command packet to USB device */
> > + msg->cmd_header.mod = mod;
> > + msg->cmd_header.cmd = offset & 0xFF;
> > + msg->cmd_header.sel = (offset >> 8) & 0xFF;
>
> In the other modules, you have some macros to combine together the cmd
> and the sel (selector, I guess?). For example from nct6694_canfd.c:
>
> #define NCT6694_CAN_DELIVER(buf_cnt) \
> ((((buf_cnt) & 0xFF) << 8) | 0x10) /* CMD|SEL */
>
> And here, you split them again. So what was the point to combine those
> together in the first place?
>
Due to these two bytes may used to OFFSET in report channel for other
modules(gpio, hwmon), I will modify them below...
> Can't you just pass both the cmd and the sel as two separate argument?
> Those cmd and sel concatenation macros are too confusing.
>
> Also, if you are worried of having too many arguments in
> nct6694_read_msg(), you may just directly pass a pointer to a struct
> nct6694_cmd_header instead of all the arguments separately.
>
...
in mfd/nct6694.c
inline struct nct6694_cmd_header nct6694_init_cmd(u8 mod, u8 cmd, u8 sel,
u16 offset, u16 length)
{
struct nct6694_cmd_header header;
header.mod = mod;
header.cmd = cmd;
header.sel = sel;
header.offset = cpu_to_le16(offset);
header.len = cpu_to_le16(length);
return header;
}
EXPORT_SYMBOL(nct6694_init_cmd);
int nct6694_read_msg(struct nct6694 *nct6694, struct nct6694_cmd_header *header,
void *buf)
{
union nct6694_usb_msg *msg = nct6694->usb_msg;
...
msg->cmd_header.mod = header->mod;
msg->cmd_header.hctrl = NCT6694_HCTRL_GET;
msg->cmd_header.len = header->len;
if (msg->cmd_header.mod == 0xFF) {
msg->cmd_header.offset = header->offset;
} else {
msg->cmd_header.cmd = header->cmd;
msg->cmd_header.sel = header->sel;
}
...
}
(also apply to nct6694_write_msg)
in other drivers, for example: gpio-nct6694.c
struct nct6694_cmd_header cmd;
int ret;
guard(mutex)(&data->lock);
cmd = nct6694_init_cmd(NCT6694_GPIO_MOD, 0, 0,
NCT6694_GPO_DIR + data->group,
sizeof(data->reg_val));
ret = nct6694_read_msg(data->nct6694, &cmd, &data->reg_val);
if (ret < 0)
return ret;
Do you think this approach would be better?
> > + msg->cmd_header.hctrl = NCT6694_HCTRL_GET;
> > + msg->cmd_header.len = cpu_to_le16(length);
> > +
...
> > +int nct6694_write_msg(struct nct6694 *nct6694, u8 mod, u16 offset,
> > + u16 length, void *buf)
> > +{
> > + union nct6694_usb_msg *msg = nct6694->usb_msg;
> > + int tx_len, rx_len, ret;
> > +
> > + guard(mutex)(&nct6694->access_lock);
> > +
> > + memset(msg, 0, sizeof(*msg));
> > +
> > + /* Send command packet to USB device */
> > + msg->cmd_header.mod = mod;
> > + msg->cmd_header.cmd = offset & 0xFF;
> > + msg->cmd_header.sel = (offset >> 8) & 0xFF;
> > + msg->cmd_header.hctrl = NCT6694_HCTRL_SET;
> > + msg->cmd_header.len = cpu_to_le16(length);
> > +
> > + ret = usb_bulk_msg(nct6694->udev,
> > + usb_sndbulkpipe(nct6694->udev, NCT6694_BULK_OUT_EP),
> > + &msg->cmd_header, sizeof(*msg), &tx_len,
> > + nct6694->timeout);
> > + if (ret)
> > + return ret;
> > +
> > + /* Send data packet to USB device */
> > + ret = usb_bulk_msg(nct6694->udev,
> > + usb_sndbulkpipe(nct6694->udev, NCT6694_BULK_OUT_EP),
> > + buf, length, &tx_len, nct6694->timeout);
> > + if (ret)
> > + return ret;
> > +
> > + /* Receive response packet from USB device */
> > + ret = usb_bulk_msg(nct6694->udev,
> > + usb_rcvbulkpipe(nct6694->udev, NCT6694_BULK_IN_EP),
> > + &msg->response_header, sizeof(*msg), &rx_len,
> > + nct6694->timeout);
> > + if (ret)
> > + return ret;
> > +
> > + /* Receive data packet from USB device */
> > + ret = usb_bulk_msg(nct6694->udev,
> > + usb_rcvbulkpipe(nct6694->udev, NCT6694_BULK_IN_EP),
> > + buf, NCT6694_MAX_PACKET_SZ, &rx_len, nct6694->timeout);
>
> What if the object size of buf is smaller than NCT6694_MAX_PACKET_SZ?
>
I will fix it to le16_to_cpu(header->len) in the v5.
> > + if (ret)
> > + return ret;
> > +
> > + if (rx_len != length) {
> > + dev_dbg(&nct6694->udev->dev, "%s: Sent length is not match!\n",
> > + __func__);
> > + return -EIO;
> > + }
> > +
> > + return nct6694_response_err_handling(nct6694, msg->response_header.sts);
> > +}
> > +EXPORT_SYMBOL(nct6694_write_msg);
> > +
> > +static void usb_int_callback(struct urb *urb)
> > +{
> > + struct nct6694 *nct6694 = urb->context;
> > + struct device *dev = &nct6694->udev->dev;
> > + unsigned int *int_status = urb->transfer_buffer;
> > + int ret;
> > +
> > + switch (urb->status) {
> > + case 0:
> > + break;
> > + case -ECONNRESET:
> > + case -ENOENT:
> > + case -ESHUTDOWN:
> > + return;
> > + default:
> > + goto resubmit;
> > + }
> > +
> > + while (*int_status) {
> > + int irq = __ffs(*int_status);
> > +
> > + generic_handle_irq_safe(irq_find_mapping(nct6694->domain, irq));
> > + *int_status &= ~BIT(irq);
> > + }
> > +
> > +resubmit:
> > + ret = usb_submit_urb(urb, GFP_ATOMIC);
> > + if (ret)
> > + dev_dbg(dev, "%s: Failed to resubmit urb, status %d",
> > + __func__, ret);
>
> Print the error mnemotecnic instead of the error code:
>
> dev_dbg(dev, "%s: Failed to resubmit urb, status %pe",
> __func__, ERR_PTR(ret));
>
> (apply to other location where you print error).
>
Understood. Fix these in v5.
> > +}
> > +
...
> > + * nct6694_read_msg - Receive data from NCT6694 USB device
> > + *
> > + * @nct6694 - Nuvoton NCT6694 structure
> > + * @mod - Module byte
> > + * @offset - Offset byte or (Select byte | Command byte)
> > + * @length - Length byte
> > + * @buf - Read data from rx buffer
> > + *
> > + * USB Transaction format:
> > + *
> > + * OUT |RSV|MOD|CMD|SEL|HCTL|RSV|LEN_L|LEN_H|
> > + * OUT |SEQ|STS|RSV|RSV|RSV|RSV||LEN_L|LEN_H|
> > + * IN |-------D------A------D------A-------|
> > + * IN ......
> > + * IN |-------D------A------D------A-------|
>
> The structure already discribes this information pretty well. No need
> for this table.
>
Drop it in v5.
> > + */
Best regards,
Ming
Powered by blists - more mailing lists