Re: [PATCH 1/1 v7] usb: serial: add support for CH348

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Johan,

On Tue, Jul 23, 2024 at 6:13 PM Johan Hovold <johan@xxxxxxxxxx> wrote:
[...]
> > > Do you need to include any copyrights from the vendor driver? It looks
> > > like at least some of the code below was copied from somewhere (but
> > > perhaps not that much).
>
> > If you - or someone else - have any advice on this I'd be happy to go with that!
>
> If you copy code directly (even if you clean it up after) you should
> include it, but not necessarily if you just use it for reference for the
> protocol.
>
> It doesn't hurt mentioning anyway when you add the reference to the
> vendor driver, for example:
>
>         Based on the XXX driver:
>
>                 https://...
>
>         Copyright YYY
Thanks, I'll include that in the next version.

[...]
> > For slow speeds I never receive the "Transmitter holding register
> > empty" interrupt/signal when using the full TX buffer.
> > It's not that the interrupt/signal is late - it just never arrives.
> > I don't know why that is (whether the firmware tries to keep things
> > "fair" for other ports, ...) though.
>
> Perhaps you can run some isolated experiments if you haven't already.
> Submitting just a single URB with say 128, 512 or 1024 bytes of data and
> see when/if you ever receive a transmitter holding empty interrupt.
>
> How does the vendor driver handle this? Does it really wait for the THRE
> interrupt before submitting more data?
The vendor driver:
- first acquires a per-device (not per port) write_lock [0]
- then waits for the (per-device, not per port) write buffer to be empty [1]
- and only then submits more data to be transmitted [2]

> You could try increasing the buffer size to 2k and see how much is
> received on the other end if you submit one URB (e.g. does the hardware
> just drop the last 1k of data when the device fifo is full).
I have not tried this yet but if still relevant (after the info about
the THRE interrupt) then I can try it and share the results.

[...]
> > > > +             * If we ingest more data then usb_serial_generic_write() will
> > > > +             * internally try to process as much data as possible with any
> > > > +             * number of URBs without giving us the chance to wait in
> > > > +             * between transfers.
> > >
> > > If the hardware really works this way, then perhaps you should not use
> > > the generic write implementation. Just maintain a single urb per port
> > > and don't submit it until the device fifo is empty.
>
> > I tried to avoid having to copy & paste (which then also means having
> > to maintain it down the line) most of the generic write
> > implementation.
> > This whole dance with waiting for the "Transmitter holding register
> > empty" by the way was the reason why parts of the transmit buffer got
> > lost, see the report from Nicolas in v6 [1]
>
> I understand, but the generic implementation is not a good fit here as
> it actively tries to make sure the device buffers are always full (e.g.
> by using two URBs back-to-back).
>
> If you can't find a way to make the hardware behave properly then a
> custom implementation using a single URBs is preferable over trying
> to limit the generic implementation like you did here. Perhaps bits can
> be reused anyway (e.g. chars_in_buffer if you use the write fifo).
I cannot find any other usb-serial driver which uses this pattern.
Most devices seem to be happy to take more data once they trigger the
write_bulk_callback but not ch348.

If there's any other (even if it's not a usb-serial) driver that I can
use as a reference implementation for your suggestion?
I'm not sure whether to use a dedicated kthread, single threaded workqueue, ...

> > > > +static struct usb_serial_driver ch348_device = {
> > > > +     .driver = {
> > > > +             .owner = THIS_MODULE,
> > > > +             .name = "ch348",
> > > > +     },
> > > > +     .id_table =             ch348_ids,
> > > > +     .num_ports =            CH348_MAXPORT,
> > > > +     .num_bulk_in =          1,
> > > > +     .num_bulk_out =         1,
> > >
> > > Set both of these to 2 so that core verifies that you have all four
> > > endpoints.
>
> > I will have to test this because I thought that:
> > - using 2 here makes usb-serial allocate an URB as well and by default
> > assign it to the first and second port
> > - usb-serial should not touch the second bulk in / bulk out endpoint
> > (as they're entirely vendor / chip specific)
>
> Setting these two should make core make sure that the endpoints exist,
> and by default they will be assigned to the first and second port, but
> you can override that calc_num_endpoints() (as you already do).
>
> For the second IN EP, you could even let core allocate the URB and use
> that instead of doing so manually (e.g. by submitting yourself or using
> the generic read implementation as mxuport does).
Thanks for the hint - I have tried this and it indeed simplifies the code!


Best regards,
Martin


[0] https://github.com/WCHSoftGroup/ch9344ser_linux/blob/d4fc95fb1cca9962384ca88b0007df8738ae5829/driver/ch9344.c#L1100
[1] https://github.com/WCHSoftGroup/ch9344ser_linux/blob/d4fc95fb1cca9962384ca88b0007df8738ae5829/driver/ch9344.c#L1152-L1156
[2] https://github.com/WCHSoftGroup/ch9344ser_linux/blob/d4fc95fb1cca9962384ca88b0007df8738ae5829/driver/ch9344.c#L1166





[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux