I have captured a few dumps when this failure is happening.  It ~always~
happens to the same type of transfer:

Enqueue: FA 2 ep2in bulk: len 13 short_ok
pack_fifo @ c5d6/2e9c fmrem
CC=f EP=2 DIR=2 CNT=0 LEN=13 MPS=64 TGL=1 ACT=1 FA=2 SPD=0 LST=1 B5=0
  fc00 2840 080d 0002
unpack_fifo @ c5d7/73 fmrem
CC=f EP=2 DIR=2 CNT=0 LEN=13 MPS=64 TGL=1 ACT=1 FA=2 SPD=0 LST=1 B5=0
  fc00 2840 080d 0002

But it does not always happen at the same instance when this PTD is sent.
Since I had this working prior to the latest changes, I incrementally
imported your latest changes and narrowed it down to the short/underrun
handling.  I'm not saying this is bug, but this is causing what I am seeing.
Below are the only changes between what I see as working what is not working
(left is the working version).  So for now, I will leave these changes out,
but I'm sure you had some good reasons for these.  I will send you some
captures that show when this is happening, maybe you can see a pattern.
>From what I can see the toggle bit is correct from the last transaction on
endpoint 2.  I have several failure logs, but I only have a log for the
working system up until mounting the partition.  After that my test that I
am using for this would likely overflow my log buffer.


For the endianness, the low level access functions are correct now.  But
because the URB transfer buffers are byte streams I needed to flip them in
read/write_ptddata_from/to_fifo() before packing them into the 16-bit data
field for isp116x_write_data except for the last byte.  I need to have
another look at it.  What I have now seems to work, but it doesn't quite
make sense to me.


The only diffs:

<working>                                                                       
    <lockup>
static void postproc_atl_queue(struct isp116x *isp116x)         static void
postproc_atl_queue(struct isp116x *isp116x)
{                                                               {
        struct isp116x_ep *ep;
struct isp116x_ep *ep;
        struct isp116x_req *req;
struct isp116x_req *req;
        struct urb *urb;
struct urb *urb;
        struct usb_device *udev;
struct usb_device *udev;
        struct ptd *ptd;
struct ptd *ptd;
        int partial_not_ok;                                   |         int
short_not_ok;
        u8 cc;                                                          u8
cc;

        for (ep = isp116x->atl_active; ep; ep = ep->active) {           for
(ep = isp116x->atl_active; ep; ep = ep->active) {
                BUG_ON(list_empty(&ep->queue));
BUG_ON(list_empty(&ep->queue));
                req = container_of(ep->queue.next, struct isp
req = container_of(ep->queue.next, struct isp
                urb = req->urb;
urb = req->urb;
                udev = urb->dev;
udev = urb->dev;
                ptd = &ep->ptd;
ptd = &ep->ptd;
                partial_not_ok = 1;                           <
                cc = PTD_GET_CC(ptd);
cc = PTD_GET_CC(ptd);

                spin_lock(&urb->lock);
spin_lock(&urb->lock);
                if (cc == TD_DATAUNDERRUN                     |
short_not_ok = urb->transfer_flags & URB_SHORT_NOT_OK
                    && !(urb->transfer_flags & URB_SHORT_NOT_ |
                        //DBG("Allowed data underrun\n");     |         /*
Data underrun is special. For allowed underrun
                                                              >
we clear the error and continue as normal. For
                                                              >
forbidden underrun we finish the DATA stage
                                                              >
immediately while for control transfer,
                                                              >
we do a STATUS stage.
                                                              >         */
                                                              >
if (cc == TD_DATAUNDERRUN){
                                                              >           if
(! short_not_ok){
                                                              >
DBG("Allowed data underrun\n");
                        cc = TD_CC_NOERROR;
cc = TD_CC_NOERROR;
                        partial_not_ok = 0;
        |           }else{
                }                                             |
ep->error_count = 1;
                if (PTD_GET_COUNT(ptd) || cc == TD_CC_NOERROR |
if (usb_pipecontrol(urb->pipe))
                        ep->error_count = 0;                  |
ep->nextpid = USB_PID_ACK;
                                                              >
else
                                                              >
usb_settoggle(udev, ep->epnum, ep->nextpid == U
                                                              >
urb->status = cc_to_error[TD_DATAUNDERRUN];
                                                              >
spin_unlock(&urb->lock);
                                                              >
continue;
                                                              >           }
                                                              >         }
                                                              >         //
Keep underrun error through the STATUS stage
                                                              >         if
(urb->status == cc_to_error[TD_DATAUNDERRUN])
                                                              >           cc
= TD_DATAUNDERRUN;
                                                              >
                                                              >
                if (cc != TD_CC_NOERROR && cc < 0x0E
if (cc != TD_CC_NOERROR && cc < 0x0E
                    && (++ep->error_count >= 3 || cc == TD_CC |
&& (++ep->error_count >= 3 || cc == TD_CC
                        if (urb->status == -EINPROGRESS)
if (urb->status == -EINPROGRESS)
                                urb->status = cc_to_error[cc]
urb->status = cc_to_error[cc]
                                                              >
//            DBG("%d: nextpid %d, status %d, err
                                                              >
if (ep->nextpid == USB_PID_ACK)
                                                              >
ep->nextpid = 0;
                        spin_unlock(&urb->lock);
spin_unlock(&urb->lock);
                        continue;
continue;
                }
-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] Behalf Of Olav
Kongas
Sent: Wednesday, January 19, 2005 6:43 AM
To: Philipp Schmid
Cc: linux-usb-devel@lists.sourceforge.net
Subject: RE: [linux-usb-devel] isp116x-hcd update




On Tue, 18 Jan 2005, Philipp Schmid wrote:
> usb-storage: usb_stor_bulk_transfer_sglist: xfer 1024 bytes, 1 entries
> usb-storage: Status code 0; transferred 832/1024              <= single PTD
> usb-storage: -- short transfer
> usb-storage: Bulk data transfer result 0x1

I haven't seen these messages. All my 3 storage devices work
smoothly. Also, usbtests #1-8 (bulk transfer tests) seem to
work reliably.

> This case did not seem to happen before importing your latest changes
> (likely because this case wasn't hit).  The main changes being PTD length
> handling in start_atl_transfers() and changes in postproc_atl_queue().
> Changing MAX_TRANSFER_SIZE_FULLSPEED doesn't seem to help.

I also changed endianness handling. Though, if there was
something wrong with that, it probably wouldn't work at all
for you. Did you have to correct endianness?

> PTDs:
>
> start_atl_transfers
> pack_fifo @ f6d6/2e8c fmrem
> CC=f EP=2 DIR=2 CNT=0 LEN=13 MPS=64 TGL=1 ACT=1 FA=2 SPD=0 LST=1 B5=0
>   fc00 2840 080d 0002
> unpack_fifo @ f6d8/7b fmrem           <= Note the late unpack

Late unpacking *shouldn't* be a problem.

> read_ptddata_from_fifo 2 13
> CC=f EP=2 DIR=2 CNT=0 LEN=13 MPS=64 TGL=1 ACT=1 FA=2 SPD=0 LST=1 B5=0
>   fc00 2840 080d 0002
> -----
> start_atl_transfers
> pack_fifo @ f6db/2e98 fmrem
> CC=f EP=2 DIR=2 CNT=0 LEN=13 MPS=64 TGL=1 ACT=1 FA=2 SPD=0 LST=1 B5=0
>   fc00 2840 080d 0002
> unpack_fifo @ f6dd/7b fmrem
> read_ptddata_from_fifo 2 13
> CC=f EP=2 DIR=2 CNT=0 LEN=13 MPS=64 TGL=1 ACT=1 FA=2 SPD=0 LST=1 B5=0
>   fc00 2840 080d 0002
> ..... continues

This log shows that the device is NAK-ing the request. One
reason may be that the device is not ready to send the last
portion of the data.

But fig.8-33 in usb 2.0 spec shows also another possible
reason: host should do the same command also when it gets
otherwise correct data, but just the toggle bit does not
match. This would mean that the device already sent the
latter portion of the data, which HC ignored, because it
expected another toggle value, while the device just has
nothing more to send.

It may well be that I haven't got the toggle bit handling
after errors right in the driver. The isp chip seems to have
its own understanding of what to do with the toggle bit in
case of errors and this does not fit with the spec; neither
have I found it documented anywhere. Perhaps your system
triggers some (recoverable) error conditions, which I don't
see here and haven't therefore straightened out.

I will take another look at the toggle bit handling. It
would help if you could post PTD dumps from both older
(working) and the latest driver versions so that the Toggle
bit history for bulk transfers could be compared.

Olav



-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel



-------------------------------------------------------
This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting
Tool for open source databases. Create drag-&-drop reports. Save time
by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc.
Download a FREE copy at http://www.intelliview.com/go/osdn_nl
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to