Bug 16607

Summary: divide error in ata_timing_compute()
Product: IO/Storage Reporter: Milan Kocian (milan.kocian)
Component: Serial ATAAssignee: Jeff Garzik (jgarzik)
Status: RESOLVED CODE_FIX    
Severity: normal CC: alan, tj
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 2.6.35.2 Subsystem:
Regression: Yes Bisected commit-id:
Attachments: call trace begin
call trace end

Description Milan Kocian 2010-08-16 16:33:27 UTC
hi all,
after upgrade from 2.6.32.5 to 2.6.35.2 I see this error when booting. Call trace attached as pictures (sorry).
I tried to look at and probably may be problem in pata_cmd64x.c where the biggest difference between versions is:

--- linux-2.6.32.5/drivers/ata/pata_cmd64x.c    2010-01-23 00:23:21.000000000 +0100
+++ linux-2.6.35.2/drivers/ata/pata_cmd64x.c    2010-08-13 22:44:56.000000000 +0200
@@ -130,8 +121,14 @@ static void cmd64x_set_timing(struct ata

                if (pair) {
                        struct ata_timing tp;
+
                        ata_timing_compute(pair, pair->pio_mode, &tp, T, 0);
                        ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP);
+                       if (pair->dma_mode) {
+                               ata_timing_compute(pair, pair->dma_mode,
+                                               &tp, T, 0);
+                               ata_timing_merge(&tp, &t, &t, ATA_TIMING_SETUP);
+                       }
                }
        }

So I tried to comment out whole 'if (pair->dma_mode)' condition (5 lines) and machine is booting now. Certainly it's not the right fix :-) but I hope it helps. I tried to analyze deeper but my knowledge is poor here.

Regards Milan Kocian
Comment 1 Milan Kocian 2010-08-16 16:35:16 UTC
Created attachment 27471 [details]
call trace begin
Comment 2 Milan Kocian 2010-08-16 16:36:03 UTC
Created attachment 27472 [details]
call trace end
Comment 3 Milan Kocian 2010-08-17 08:15:06 UTC
hi,
I have more info about it. Divide error happens on line:

#define ENOUGH(v, unit)         (((v)-1)/(unit)+1)
#define EZ(v, unit)             ((v)?ENOUGH(v, unit):0)
/*((t->udma       * 1000)?(((t->udma       * 1000)-1)/(0)+1):0)*/
static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
{
        q->setup        = EZ(t->setup      * 1000,  T);
        q->act8b        = EZ(t->act8b      * 1000,  T);
        q->rec8b        = EZ(t->rec8b      * 1000,  T);
        q->cyc8b        = EZ(t->cyc8b      * 1000,  T);
        q->active       = EZ(t->active     * 1000,  T);
        q->recover      = EZ(t->recover    * 1000,  T);
        q->dmack_hold   = EZ(t->dmack_hold * 1000,  T);
        q->cycle        = EZ(t->cycle      * 1000,  T);
        printk("MM: Still ok\n");
!!-->        q->udma         = EZ(t->udma       * 1000, UT);
        printk("MM: NOT DONE\n");
}

in function 'static void ata_timing_quantize' where UT is zero. I see problem in commit d62f5576efc4886c0f3633c2652c3a924e043be9:

--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -131,8 +131,14 @@ static void cmd64x_set_timing(struct ata_port *ap, struct ata_device *adev, u8 m
 
                if (pair) {
                        struct ata_timing tp;
+
                        ata_timing_compute(pair, pair->pio_mode, &tp, T, 0);
                        ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP);
+                       if (pair->dma_mode) {
+                               ata_timing_compute(pair, pair->dma_mode,
+                                               &tp, T, 0);
+                               ata_timing_merge(&tp, &t, &t, ATA_TIMING_SETUP);
+                       }
                }
        }

Where ata_timing_compute() is called with UT = 0 which is not correct for XFER_UDMA_5 mode. (pair->dma_mode = XFER_UDMA_5 in my case). I'm not sure how to change UT value so I'm waiting for reply :-).
Comment 4 Tejun Heo 2010-08-17 08:17:37 UTC
cc'ing Alan Cox.  Alan, can you please take a look?  Thanks.
Comment 5 Alan 2010-08-17 09:47:13 UTC
Nothing to do with me

Ask Bartlomiej

commit d62f5576efc4886c0f3633c2652c3a924e043be9
Author: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Date:   Mon Jan 18 18:15:04 2010 +0100

    pata_cmd64x: fix handling of address setup timings
    
    Account for the requirements of the DMA mode currently used
    by the pair device.
    
    Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
    Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Comment 6 Tejun Heo 2010-08-17 10:14:19 UTC
Bartlomiej?
Comment 7 Bartlomiej Zolnierkiewicz 2010-08-17 11:20:40 UTC
The patch in question has never been submitted to upstream kernel and was only posted as a part of atang tree update:

http://lkml.org/lkml/2010/1/18/256
http://patchwork.ozlabs.org/patch/43145/
http://lkml.org/lkml/2010/1/20/443

I have a very little control over what people are doing with my patches posted to public mailing lists (as a part of Q&A process of atang tree).. 

Unfortunately I don't have any time these days to work on this or any other kernel problems that are not covered by support or work contract so it would be the best to ping the upstream kernel maintainer (Jeff) w.r.t. resolution of the upstream kernel bug..
Comment 8 Tejun Heo 2010-08-17 12:18:31 UTC
Patch to revert the offending commit is posted.

  http://article.gmane.org/gmane.linux.ide/47055

Thanks.
Comment 9 Milan Kocian 2010-08-27 07:52:36 UTC
Hi,

exists any reason not to be in stable yet ? 

thanks.
Comment 10 Milan Kocian 2010-09-21 11:39:49 UTC
Patch has been already applied.