Consider a USB-attached serial port that is set to do RTS/CTS (or
DSR/DTR) handshaking: What stops the kernel sending more data to it when
the remote end lowers CTS (or DTR)?
On Thu, Feb 14, 2008 at 01:15:37AM +1030, David Newall wrote:
> Consider a USB-attached serial port that is set to do RTS/CTS (or
> DSR/DTR) handshaking: What stops the kernel sending more data to it when
> the remote end lowers CTS (or DTR)?
The tty layer should look at the proper flags and not send data on to
the driver in this kind of instance.
Is this not happening properly for you? If so, which USB serial driver?
thanks,
greg k-h
Greg KH wrote:
> On Thu, Feb 14, 2008 at 01:15:37AM +1030, David Newall wrote:
>
>> Consider a USB-attached serial port that is set to do RTS/CTS (or
>> DSR/DTR) handshaking: What stops the kernel sending more data to it when
>> the remote end lowers CTS (or DTR)?
>>
>
> The tty layer should look at the proper flags and not send data on to
> the driver in this kind of instance.
>
> Is this not happening properly for you? If so, which USB serial driver?
>
It's not happening properly, for pl2303 (and, I admit it! on kernel
2.4.) I think there's a widespread problem (i.e. with other drivers.)
None of the drivers that I've examined check CTS or DTR; or, if they do,
I can't see where. Likewise, I can't see it being done in n_tty nor
tty_io; not even in usbserial. The best answer I can see is write_room,
but that doesn't seem quite right. It seems that data written (via
*_write) will merrily be transmitted to the converter, even while the
remote end is signalling to stop, even if local hardware buffers fill.
I have a working solution for the 2.4 driver, but am looking towards
something for 2.6 and beyond. The 2.4 solution is in two parts: first,
implement a write_room function, which returns 0 when transmission is
required to stop, which apparently gives a hint to the tty layer. (NB,
doesn't help when using a different line discipline.) The second part
is to return 0 (or maybe -EAGAIN?) in the write function when
transmission is required to stop. This appears sound. (Note that the
generic putchar does no error checking, and fails when the write URB is
busy. That's a problem with a fairly obvious solution.)
The current 2.6 driver maintains it's own buffer. I think that's a bad
thing: usbserial already buffers writes, and the extra buffer copy seems
unnecessary, however it does solve the putchar problem. Buffered (i.e.
by the 2.6 series pl2303 driver) data is written as soon as practicable,
regardless of CTS/DTR. The same general workaround, but placed in
pl2303_send seems correct to me; that is, stop submitting write urbs
when the remote end lowers CTS/DTR, and trigger the resume from the
interrupt callback (specifically in update_line_status.)
As I say, this appears to be a widespread problem. I've looked at a
number of drivers and in none of them can I see anything to prevent
transmission when the remote end demands a stop. I'm not sure that the
tty layer, which I think I said attempts to address the problem, albeit
it does a half-arsed job, is the right place to do hardware
handshaking. Equally, I'm not sure that the wheel should be re-invented
for every driver, but that might be unavoidable.
To make it clear: Even aside from the buffer in 2.6's pl2303.c, there's
a race: An in-flight write URB can fill all hardware buffers, making
unsafe what previously appeared to be a safe write. I think it's
essential to delay submission of the URB on a stop-transmit condition.
On Wed, 13 Feb 2008 21:02:11 -0800
Greg KH <[email protected]> wrote:
> On Thu, Feb 14, 2008 at 01:15:37AM +1030, David Newall wrote:
> > Consider a USB-attached serial port that is set to do RTS/CTS (or
> > DSR/DTR) handshaking: What stops the kernel sending more data to it when
> > the remote end lowers CTS (or DTR)?
>
> The tty layer should look at the proper flags and not send data on to
> the driver in this kind of instance.
For outgoing data the tty ldisc will check the available room indicators
the driver provides and stop when they fill. We don't want to be directly
involved in flow control if possible as most decent hardware does RTS/CTS
handshaking in hardware (except in the PC world).
If your hardware is dumb (ie you do RTS/CTS in software) then you need to
track the CTS state and termios bits (in your set_termios method) and
transmit according to flow control rules, letting the buffer fill up
otherwise.
Alan
> To make it clear: Even aside from the buffer in 2.6's pl2303.c, there's
> a race: An in-flight write URB can fill all hardware buffers, making
> unsafe what previously appeared to be a safe write. I think it's
> essential to delay submission of the URB on a stop-transmit condition.
Hardware flow control *is* a race, and always will be. The remote end has
a delay in signalling 'stop' there is a propogation delay and a response
delay. This is why most implementations assert stop a bit *before* they
run out.
Given the size of transfers and the internal buffering one would hope the
USB devices do their own flow control if told to properly.
Alan
On Thursday 14 February 2008, Alan Cox wrote:
>> To make it clear: Even aside from the buffer in 2.6's pl2303.c, there's
>> a race: An in-flight write URB can fill all hardware buffers, making
>> unsafe what previously appeared to be a safe write. I think it's
>> essential to delay submission of the URB on a stop-transmit condition.
>
>Hardware flow control *is* a race, and always will be. The remote end has
>a delay in signalling 'stop' there is a propogation delay and a response
>delay. This is why most implementations assert stop a bit *before* they
>run out.
>
>Given the size of transfers and the internal buffering one would hope the
>USB devices do their own flow control if told to properly.
>
>Alan
Apparently they do not Alan, the pl2303 in particular is a problem child,
throwing several lost com errors a day when doing nothing more strenuous than
talking to my belkin UPS from apcupsd, very small packets there, 20 bytes I
believe at several second intervals. I can cut those messages to about
weekly by using an FDTI adaptor in its place, or I can stop them entirely if
a pure rs232 connection is used. Unforch, pure rs232 is going the way of the
dodo bird, and the adapters in general fail such applications badly. I want
to build a new machine, but the first thing I'd have to get after a new video
card is a serial card. And there goes a slot I'll need for something else.
My current home automation via heyu, the ups, and the Garmin GPS all require
serial ports.
Another linux app, a route navigator program that uses the output of a GPS to
display where you are, also has errors several times an hour when using a
pl2303 to connect a low baud rate Garmin 12 with no flow control to it. I
just recently used it for a 3000 mile nearly month long trip.
So IMO, neither of the 2 readily available devices for usb-serial use is quite
ready for mission critical usage.
--
Cheers, Gene
"There are four boxes to be used in defense of liberty:
soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author)
No extensible language will be universal.
-- T. Cheatham
O> believe at several second intervals. I can cut those messages to about
> weekly by using an FDTI adaptor in its place, or I can stop them entirely if
Sorry don't see the connection between the two stories ?
Alan
Alan Cox wrote:
>> To make it clear: Even aside from the buffer in 2.6's pl2303.c, there's
>> a race: An in-flight write URB can fill all hardware buffers, making
>> unsafe what previously appeared to be a safe write. I think it's
>> essential to delay submission of the URB on a stop-transmit condition.
>>
>
> Hardware flow control *is* a race, and always will be. The remote end has
> a delay in signalling 'stop' there is a propogation delay and a response
> delay. This is why most implementations assert stop a bit *before* they
> run out.
>
That's a very good point. Even so: on the 2.4 driver, write_room isn't
implemented (refer to a previous message by Alan); and in 2.6, a 1k
buffer is built into the driver, with nothing to prevent it being sent
when the hardware buffer fills. These could be bugs in the two versions
of pl2303, if you like; in fact I suppose they are; but there's a wider
problem: The same weakness can be found in aircable.c, airprime.c,
cyberjack.c, cypress_m8.c (I think), empeg.c, ftdi_sio (I think),
io_ti.c, and that's where I stop checking, and declare it's widespread.
> Given the size of transfers and the internal buffering one would hope the
> USB devices do their own flow control if told to properly.
>
RS232 is (normally) so much slower than USB that, on an extended
transmission, the buffer internal to the local hardware can fill well
before the remote device has demanded that transmission stop. In fact,
now that you've mentioned it, I can't see that anything to stop the
driver from overflowing the internal buffer, which is very perplexing.
Would that be right? That seems a pretty dramatic weakness; how do you
write a large report to a slow printer without losing data?
I'm beginning to realise that overflowing the internal buffer is the
greatest risk of data loss. Hardware flow control almost seems
serendipitous. It gives us a reason to stop submitting bulk writes.
This is the essence of the change that I looking at for pl2303.c.
(Patch relative to kernel 2.6.23.14.) Does it make sense?
--- pl2303.c 2008-01-15 07:19:56.000000000 +1030
+++ pl2303.c.new 2008-02-15 04:22:12.000000000 +1030
@@ -370,6 +370,18 @@
spin_lock_irqsave(&priv->lock, flags);
+ /*
+ * there's a limit to how much we can buffer, so don't accept data while
+ * CTS or DSR are low. XXX I don't know what to do about XON/XOFF.
+ */
+ if ((priv->line_control | CONTROL_RTS && !(priv->line_status & UART_CTS)) || \
+ (priv->line_control | CONTROL_DTR && !(priv->line_status & UART_DSR))) {
+ /*
+ spin_unlock_irqrestore(&priv->lock, flags);
+ dbg("%s: send paused by remote flow control", __FUNCTION__);
+ return;
+ }
+
if (priv->write_urb_in_use) {
spin_unlock_irqrestore(&priv->lock, flags);
return;
@@ -957,6 +969,9 @@
pl2303_update_line_status(port, data, actual_length);
+ /* send any buffered data */
+ pl2303_send(port);
+
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
On Thursday 14 February 2008, David Newall wrote:
> RS232 is (normally) so much slower than USB that, on an extended
> transmission, the buffer internal to the local hardware can fill well
> before the remote device has demanded that transmission stop. ?In fact,
> now that you've mentioned it, I can't see that anything to stop the
> driver from overflowing the internal buffer, which is very perplexing.
> Would that be right?
Only for stupidly designed hardware ... which you might well
be using, though I happen to never have seen anything that's
quite *that* stupid. (There's always a first time though.)
USB has enough control flow to prevent that from happening.
If the host sends data that the peripheral isn't ready to
accept, the peripheral just refuses to accept it, and the
host will retry later.
- Dave
On Thursday 14 February 2008, Alan Cox wrote:
>O> believe at several second intervals. I can cut those messages to about
>
>> weekly by using an FDTI adaptor in its place, or I can stop them entirely
>> if
>
>Sorry don't see the connection between the two stories ?
>
>Alan
The connection is that windows people don't see those errors, linux folks do.
I believe, but don't know how to use the tools to verify it, that the first
byte of a packet is being thrown away about .1% of the time for the pl2303,
but I'm not sure if the FTDI driver still suffers from a similar rash. I
have only one such FTDI adapter in the system atm, and its in series with
manual heyu commands only, so it doesn't get regularly exercised. I figure
it will do the least damage there. The pl2303's are all hanging on a peg
waiting for emergency use only, they were just too much trouble when they
miss-fire and the system issues -wall warnings several times per hour.
--
Cheers, Gene
"There are four boxes to be used in defense of liberty:
soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author)
The revolution will not be televised.
> That's a very good point. Even so: on the 2.4 driver, write_room isn't
> implemented (refer to a previous message by Alan); and in 2.6, a 1k
> buffer is built into the driver, with nothing to prevent it being sent
> when the hardware buffer fills. These could be bugs in the two versions
Which isn't a bug if the hardware handles it internally as most does.
> of pl2303, if you like; in fact I suppose they are; but there's a wider
> problem: The same weakness can be found in aircable.c, airprime.c,
> cyberjack.c, cypress_m8.c (I think), empeg.c, ftdi_sio (I think),
> io_ti.c, and that's where I stop checking, and declare it's widespread.
Careful - a lot of hardware handles this properly itself, you simply
don't get the URB completing until its all done.
> now that you've mentioned it, I can't see that anything to stop the
> driver from overflowing the internal buffer, which is very perplexing.
> Would that be right? That seems a pretty dramatic weakness; how do you
> write a large report to a slow printer without losing data?
pl2303 implements write room in 2.6 (and 2.4 I don't care about at all)
so the driver appears entirely correct in respect of its internal buffer
management. Someone with docs will have to comment on whether it handles
flow control in firmware or needs pl2303_send to do further checks as you
propose.
Alan
> byte of a packet is being thrown away about .1% of the time for the pl2303,
> but I'm not sure if the FTDI driver still suffers from a similar rash. I
A 20 byte low speed message is too small for flow control to account for
it.
On Thursday 14 February 2008, Alan Cox wrote:
>> byte of a packet is being thrown away about .1% of the time for the
>> pl2303, but I'm not sure if the FTDI driver still suffers from a similar
>> rash. I
>
>A 20 byte low speed message is too small for flow control to account for
>it.
Where then could the first byte go? Note I'm not fussing about flow controls
per sei, so the subject line maybe needs to be adjusted, but they obviously
work well enough that a multimegabyte transfer to my printer works very well,
but about usb trying to entirely replace serial here. There does seem to be
a problem but I'm not 100% positive where it is in the chain of a usb packets
travels. What I've observed, with hidraw I think it was, is that the
first 'wake up' byte incoming didn't seem to be there.
--
Cheers, Gene
"There are four boxes to be used in defense of liberty:
soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author)
Whenever people agree with me I always feel I must be wrong.
-- Oscar Wilde
On Thu, Feb 14, 2008 at 07:55:44PM +1030, David Newall wrote:
> The current 2.6 driver maintains it's own buffer. I think that's a bad
> thing: usbserial already buffers writes, and the extra buffer copy seems
> unnecessary, however it does solve the putchar problem. Buffered (i.e.
> by the 2.6 series pl2303 driver) data is written as soon as practicable,
> regardless of CTS/DTR. The same general workaround, but placed in
> pl2303_send seems correct to me; that is, stop submitting write urbs
> when the remote end lowers CTS/DTR, and trigger the resume from the
> interrupt callback (specifically in update_line_status.)
Where does the usbserial core buffer writes on 2.6? The serial_write()
function just passes the data straight down to the usb-serial child
driver directly, no copying or buffering happens that I can see.
> To make it clear: Even aside from the buffer in 2.6's pl2303.c, there's
> a race: An in-flight write URB can fill all hardware buffers, making
> unsafe what previously appeared to be a safe write. I think it's
> essential to delay submission of the URB on a stop-transmit condition.
It's up to the individual driver to know when their buffers are filled
up. The big problem is, a lot of these cheap usb-serial devices (like
the pl2303) don't have a way to report the uart queue filled-state back
to the host, so things can easily get over-run as you have found out.
If you really want to use a usb-serial device in an environment where
such kinds of flow control are essential, then you have to buy the more
expensive ones. The I/O networks devices handle this kind of thing very
well, and have done so since the 2.3 days, but they cost much more than
the cheap pl2303-based devices.
thanks,
greg k-h
On Thu, Feb 14, 2008 at 03:04:41PM -0500, Gene Heskett wrote:
> On Thursday 14 February 2008, Alan Cox wrote:
> >> byte of a packet is being thrown away about .1% of the time for the
> >> pl2303, but I'm not sure if the FTDI driver still suffers from a similar
> >> rash. I
> >
> >A 20 byte low speed message is too small for flow control to account for
> >it.
>
> Where then could the first byte go? Note I'm not fussing about flow controls
> per sei, so the subject line maybe needs to be adjusted, but they obviously
> work well enough that a multimegabyte transfer to my printer works very well,
> but about usb trying to entirely replace serial here. There does seem to be
> a problem but I'm not 100% positive where it is in the chain of a usb packets
> travels. What I've observed, with hidraw I think it was, is that the
> first 'wake up' byte incoming didn't seem to be there.
I have not seen this kind of error in years, why have you not reported
it?
Can you enable debugging in the pl2303 driver with a simple:
modprobe pl2303 debug=1
or when the driver is running with:
echo 1 > /sys/module/pl2303/parameters/debug
That way you can see the data flowing through the device. If the host
sends it to the device, perhaps your device is just dropping it somehow?
These pl2303 devices are really cheap, there are lots of different
variations of them, and none of them are documented at all. We might be
missing some kind of interaction here, but in my tests, I have not had
any lost data.
Are you sure your userspace program isn't constantly setting the line
settings? We have seen instances where the device does get confused and
resets itself if that happens a lot. That was just fixed in the last
kernel release.
thanks,
greg k-h
On Thursday 14 February 2008, Greg KH wrote:
>On Thu, Feb 14, 2008 at 03:04:41PM -0500, Gene Heskett wrote:
>> On Thursday 14 February 2008, Alan Cox wrote:
>> >> byte of a packet is being thrown away about .1% of the time for the
>> >> pl2303, but I'm not sure if the FTDI driver still suffers from a
>> >> similar rash. I
>> >
>> >A 20 byte low speed message is too small for flow control to account for
>> >it.
>>
>> Where then could the first byte go? Note I'm not fussing about flow
>> controls per sei, so the subject line maybe needs to be adjusted, but they
>> obviously work well enough that a multimegabyte transfer to my printer
>> works very well, but about usb trying to entirely replace serial here.
>> There does seem to be a problem but I'm not 100% positive where it is in
>> the chain of a usb packets travels. What I've observed, with hidraw I
>> think it was, is that the first 'wake up' byte incoming didn't seem to be
>> there.
>
>I have not seen this kind of error in years, why have you not reported
>it?
I did make some noise, probably over a year ago now, but I guess it fell
through the cracks or no one else could duplicate it. And my expiry on this
list means any and all such messages have been expired for several months.
>Can you enable debugging in the pl2303 driver with a simple:
> modprobe pl2303 debug=1
>or when the driver is running with:
> echo 1 > /sys/module/pl2303/parameters/debug
>
>That way you can see the data flowing through the device. If the host
>sends it to the device, perhaps your device is just dropping it somehow?
>
>These pl2303 devices are really cheap, there are lots of different
>variations of them, and none of them are documented at all. We might be
>missing some kind of interaction here, but in my tests, I have not had
>any lost data.
I have two, both very early models sold by Radio Shack but they have been
hanging on the pegs except for when I take roadnav with me on a long trip.
>Are you sure your userspace program isn't constantly setting the line
>settings? We have seen instances where the device does get confused and
>resets itself if that happens a lot. That was just fixed in the last
>kernel release.
Maybe that is what I was seeing? ATM runing on 2.6.24 final. Just for grins I
fired up a 'cat /dev/hideaw0 | hexdump -v' and I'm seeing traffic, mostly
from the motion sensor, but because hexdump makes a 16 byte line out of one
byte, and may display that byte anyplace in that 16 byte buffer, I can't tell
what is right and what is wrong even though I am familiar with the x10
protocol. Do we have another such tool that will output only those bytes
actually received as they come in? Something that prints the hex value of
the byte, and then issues a newline to the screen? Or some way to ship the
$00's to /dev/null so hexdump ignores them?
>thanks,
>
>greg k-h
--
Cheers, Gene
"There are four boxes to be used in defense of liberty:
soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author)
"But I don't like Spam!!!!"
Gene Heskett <[email protected]> writes:
> Apparently they do not Alan, the pl2303 in particular is a problem child,
> throwing several lost com errors a day when doing nothing more strenuous than
> talking to my belkin UPS from apcupsd, very small packets there, 20 bytes I
> believe at several second intervals.
Is your UPS using "modern" hardware handshaking (CTS = PC can send,
with RTS practically always asserted)? Or perhaps the "old",
"half-duplex" V.24-style (RTS asserted before TX and then waiting for
CTS)?
Are you sure it uses hw handshaking at all? Most (all?) UPSes I used
had only TxD and RxD (for RS-232).
--
Krzysztof Halasa
On Thursday 14 February 2008, Krzysztof Halasa wrote:
>Gene Heskett <[email protected]> writes:
>> Apparently they do not Alan, the pl2303 in particular is a problem child,
>> throwing several lost com errors a day when doing nothing more strenuous
>> than talking to my belkin UPS from apcupsd, very small packets there, 20
>> bytes I believe at several second intervals.
>
>Is your UPS using "modern" hardware handshaking (CTS = PC can send,
>with RTS practically always asserted)? Or perhaps the "old",
>"half-duplex" V.24-style (RTS asserted before TX and then waiting for
>CTS)?
>
>Are you sure it uses hw handshaking at all? Most (all?) UPSes I used
>had only TxD and RxD (for RS-232).
ATM, its plugged into a USB port, but for some reason was not recognized at
the last bootup. And I just installed the rpm for a newer version of apcupsd
when I found apcupsd was logging an error and exiting about 2 seconds after
being started by the 'service' utility. So I'm a bit puzzled. From the
dmesg at boot time there is no mention of it being found, from the current
dmesg, after unplugging the USB cable from the back of it and replugging it
about a second later, and got this:
[180077.652645] usb 1-1.1: USB disconnect, address 6
[180080.387154] usb 1-1.1: new low speed USB device using ehci_hcd and address
11
[180080.586706] usb 1-1.1: configuration #1 chosen from 1 choice
[180081.339062] hiddev97hidraw3: USB HID v1.11 Device [Belkin Belkin UPS] on
usb-0000:00:02.2-1.1
As to why it wasn't found at bootup, call me bumfuzzled. Uptime is about 2d
3h and I wasn't aware it wasn't running until I wanted to see if anything was
different about how it handled my belkin, which is not well, but it does take
care of the graceful shutdown.
I just found this:
[root@coyote ~]# dmesg |grep -A2 'address 6'
[ 30.990194] usb 1-1.1: new low speed USB device using ehci_hcd and address
6
[ 31.183832] usb 1-1.1: configuration #1 chosen from 1 choice
[ 31.190504] usb 1-1.1: can't set config #1, error -32
--
[180077.652645] usb 1-1.1: USB disconnect, address 6
[180080.387154] usb 1-1.1: new low speed USB device using ehci_hcd and address
11
[180080.586706] usb 1-1.1: configuration #1 chosen from 1 choice
So something wasn't available at bootup. And I'm still puzzled...
--
Cheers, Gene
"There are four boxes to be used in defense of liberty:
soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author)
The most important early product on the way to developing a good product
is an imperfect version.
Alan Cox wrote:
>> byte of a packet is being thrown away about .1% of the time for the pl2303,
>> but I'm not sure if the FTDI driver still suffers from a similar rash. I
>>
>
> A 20 byte low speed message is too small for flow control to account for
> it.
I agree. I've observed the first byte of received data disappears on
pl2303 devices, but haven't spent time finding out why. (It's on my list.)
Greg KH wrote:
> On Thu, Feb 14, 2008 at 07:55:44PM +1030, David Newall wrote:
>
>> The current 2.6 driver maintains it's own buffer. I think that's a bad
>> thing: usbserial already buffers writes, and the extra buffer copy seems
>> unnecessary, however it does solve the putchar problem. Buffered (i.e.
>> by the 2.6 series pl2303 driver) data is written as soon as practicable,
>> regardless of CTS/DTR. The same general workaround, but placed in
>> pl2303_send seems correct to me; that is, stop submitting write urbs
>> when the remote end lowers CTS/DTR, and trigger the resume from the
>> interrupt callback (specifically in update_line_status.)
>>
>
> Where does the usbserial core buffer writes on 2.6? The serial_write()
> function just passes the data straight down to the usb-serial child
> driver directly, no copying or buffering happens that I can see.
>
You're right. I haven't examined the 2.6 stack as closely as the 2.4.
I noticed the buffer in 2.6 pl2303, but didn't check 2.6 usb-serial. I
think I prefer the buffer in usb-serial, because its centralised rather
than in each driver, but I'm not going to step up to the plate and
propose changing that!
>> To make it clear: Even aside from the buffer in 2.6's pl2303.c, there's
>> a race: An in-flight write URB can fill all hardware buffers, making
>> unsafe what previously appeared to be a safe write. I think it's
>> essential to delay submission of the URB on a stop-transmit condition.
>>
>
> It's up to the individual driver to know when their buffers are filled
> up. The big problem is, a lot of these cheap usb-serial devices (like
> the pl2303) don't have a way to report the uart queue filled-state back
> to the host, so things can easily get over-run as you have found out.
>
My understanding of the problem has developed over the last couple of
days; going from wrist-deep to elbow-deep into the guts of things does
that. There is a problem, and the solution I've been developing
addresses it, but maybe there's a simpler answer. Hope to have a patch
together soon.
Gene Heskett <[email protected]> wrote:
['cat /dev/hideaw0 | hexdump -v']
> Or some way to ship the
> $00's to /dev/null so hexdump ignores them?
.. | perl -pe 's/\00//g/' | ...
Alan,
Alan Cox wrote:
>> That's a very good point. Even so: on the 2.4 driver, write_room isn't
>> implemented (refer to a previous message by Alan); and in 2.6, a 1k
>> buffer is built into the driver, with nothing to prevent it being sent
>> when the hardware buffer fills.
>>
[...]
> Careful - a lot of hardware handles this properly itself, you simply
> don't get the URB completing until its all done.
>
I am incredibly grateful to you for telling me this. I didn't know it
and hadn't noticed that that was occurring; it was. I thought data was
being lost by the converter -- I could see where it was missing on the
screen! -- but it's actually a bug in the tty layer.
Here's what really was happening: The PL2303 contains a 256 byte buffer,
and write URBs don't complete when that's full, as you said. At such
times, that is when a bulk write was pending, the tty layer could and
would still call pl2303_write, which would return 0. The tty layer
would loop, trying one byte followed by the remaining count, repeating
until no data remained. The following clause, from write_chan in
n_tty.c, appears responsible; it is within a while(1) loop:
if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) {
while (nr > 0) {
ssize_t num = opost_block(tty, b, nr);
if (num < 0) {
if (num == -EAGAIN)
break;
retval = num;
goto break_out;
}
b += num;
nr -= num;
if (nr == 0)
break;
get_user(c, b);
if (opost(c, tty) < 0)
break;
b++; nr--;
}
if (tty->driver.flush_chars)
tty->driver.flush_chars(tty);
} ...
Note that opost() assumes that driver.putchar (which translates to a
one-byte write) always succeeds. This behaviour is documented.
By the way, the true cause of the problem was somewhat disguised by the
fact that space in the PL2303's buffer could become available part-way
through the cycle, causing non-deterministic (i.e. not exactly
reproducible) loss of part of a write; it looked exactly like a flow
control problem.
The (2.4, remember) PL2303 driver has no write_room function, which I
gather is the appropriate place to signal that a write cannot be
performed. Providing one that returns 0 when the (singleton) write urb
is busy, resolves the issue. The patch that I had previously been
developing is entirely wrong. Oh well. Mind you, providing a
write_room function is NOT a real solution; it merely reduces the
condition to a usually-winnable race. (Ironically, when I back-ported
the 2.6 driver, I excluded its new write_room function. Mistake.)
Thanks for the nugget.
> developing is entirely wrong. Oh well. Mind you, providing a
> write_room function is NOT a real solution; it merely reduces the
> condition to a usually-winnable race. (Ironically, when I back-ported
> the 2.6 driver, I excluded its new write_room function. Mistake.)
What race do you see left ?
Alan Cox wrote:
>> developing is entirely wrong. Oh well. Mind you, providing a
>> write_room function is NOT a real solution; it merely reduces the
>> condition to a usually-winnable race. (Ironically, when I back-ported
>> the 2.6 driver, I excluded its new write_room function. Mistake.)
>>
>
> What race do you see left ?
>
On second thoughts I'm not sure that I do. I've had my head so full of
2.4 pl2303, and 2.4 pl2303 with this, that and the other added to it,
that I was probably just confused. Certainly it's not important,
because I didn't mean the 2.6 driver, but an hypothetical 2.4 with a
simplistic write_room function added (e.g. return
port->write_urb->status == -EINPROGRESS ? 0 : 64). OPOST processing's
use of putchar to expand CRLF sends two writes (or putchars), with no
intervening checks. Since I'm just polishing off my back-port of
2.6.24.1 pl2303 to kernel 2.4, the matter is quite irrelevant.
By the way, what happened to HUawei E620 UMTS/HSDPA card? It's in
pl2303 in 2.6.23; not in 2.6.24.1. (Do I remove it from my back-port?)
On Fri, Feb 22, 2008 at 06:05:09AM +1030, David Newall wrote:
> Alan Cox wrote:
> >> developing is entirely wrong. Oh well. Mind you, providing a
> >> write_room function is NOT a real solution; it merely reduces the
> >> condition to a usually-winnable race. (Ironically, when I back-ported
> >> the 2.6 driver, I excluded its new write_room function. Mistake.)
> >>
> >
> > What race do you see left ?
> >
>
> On second thoughts I'm not sure that I do. I've had my head so full of
> 2.4 pl2303, and 2.4 pl2303 with this, that and the other added to it,
> that I was probably just confused. Certainly it's not important,
> because I didn't mean the 2.6 driver, but an hypothetical 2.4 with a
> simplistic write_room function added (e.g. return
> port->write_urb->status == -EINPROGRESS ? 0 : 64). OPOST processing's
> use of putchar to expand CRLF sends two writes (or putchars), with no
> intervening checks. Since I'm just polishing off my back-port of
> 2.6.24.1 pl2303 to kernel 2.4, the matter is quite irrelevant.
>
> By the way, what happened to HUawei E620 UMTS/HSDPA card? It's in
> pl2303 in 2.6.23; not in 2.6.24.1. (Do I remove it from my back-port?)
Yes, please remove it, it was incorrectly listed in the pl2303 driver in
the .23 kernel.
thanks,
greg k-h