lkml.org 
[lkml]   [2002]   [May]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH] IDE PIO write Fix #2
Martin Dalecki wrote:

> U¿ytkownik Linus Torvalds napisa³:
> > In article <3CE0D6DE.8090407@evision-ventures.com>,
> > Martin Dalecki <dalecki@evision-ventures.com> wrote:
> >
> >>>--- linux-2.5.15/drivers/ide/ide-taskfile.c.orig Fri May 10 11:49:35 2002
> >>>+++ linux-2.5.15/drivers/ide/ide-taskfile.c Tue May 14 10:40:43 2002
> >>>@@ -606,7 +606,7 @@
> >>> if (!ide_end_request(drive, rq, 1))
> >>> return ide_stopped;
> >>>
> >>>- if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) {
> >>>+ if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) {
> >>
> >
> > Well, that's definitely an improvement - the original code makes no
> > sense at all, since it's doing a bitwise xor on two bits that are not
> > the same, and then uses that as a boolean value.
> >
> > Your change at least makes it use the bitwise xor on properly logical
> > values, making the bitwise xor work as a _logical_ xor.
> >
> > Although at that point I'd just get rid of the xor, and replace it by
> > the "!=" operation - which is equivalent on logical ops.
> >
> >
> >>> pBuf = ide_map_rq(rq, &flags);
> >>> DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors);
> >>
> >>
> >>Hmm. There is something else that smells in the above, since the XOR operator
> >>doesn't seem to be proper. Why shouldn't we get DRQ_STAT at all on short
> >>request? Could you perhaps just try to replace it with an OR?
> >
> >
> > The XOR operation is a valid op, if you just use it on valid values,
> > which the patch does seem to make it do.
> >
> > I don't know whether the logic is _correct_ after that, but at least
> > there is some remote chance that it might make sense.
> >
> > Linus
>
> As far as I can see the patch makes sense. It is just exposing a problem
> which was hidden before.

The original code:
a) if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) {
is being compared to these expressions:
b) logical equ. if ((rq->current_nr_sectors==1) || ((stat & DRQ_STAT)!=0)) { (me)
c) not eqival. if ((rq->current_nr_sectors==1) ^ ((stat & DRQ_STAT)!=0)) { (tomita)
d) same as c if ((rq->current_nr_sectors==1) != ((stat & DRQ_STAT)!=0)) { (linus)

Note: DRQ_STAT will be set when this routine is entered per "PIO Out protocol spec".

c+d will deadlock.
(it will _not_ send the last sector)

a+b will send the last sector to the drive when it isn't ready to receive.
(Although most of the time it _will_ be ready when we enter this routine)

So:
if( (stat & DRQ_STAT) && !(stat & BSY_STAT)) {
should be correct.

The original intent for a) was probably:
check DRQ only on the _first_ sector we transfer as
shown in "ATA-4 PIO data out command protocol", which would translate to:
e) if ( !(rq->are_we_transferring_the_first_sector_just_now) || ((stat & DRQ_STAT)!=0)) {

-
Gunther

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:26    [W:0.069 / U:0.088 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site