All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
To: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Cc: Randy Dunlap <randy.dunlap@oracle.com>, Mark Lord <lkml@rtr.ca>,
	Nick Warne <nick@ukfsn.org>,
	linux-kernel@vger.kernel.org, linux-ide@vger.kernel.org
Subject: Re: Peculiar out-of-sync boot log lines
Date: Sun, 9 Dec 2007 16:44:03 +0100	[thread overview]
Message-ID: <200712091644.03448.bzolnier@gmail.com> (raw)
In-Reply-To: <47597612.4080508@ru.mvista.com>


Hi,

On Friday 07 December 2007, Sergei Shtylyov wrote:
> Hello.
> 
> Bartlomiej Zolnierkiewicz wrote:
> 
> > [PATCH] ide: DMA reporting and validity checking fixes (take 2)
> 
> > * ide_xfer_verbose() fixups:
> >   - beautify returned mode names
> >   - fix PIO5 reporting
> >   - make it return 'const char *'
> 
> > * Change printk() level from KERN_DEBUG to KERN_INFO in ide_find_dma_mode().
> 
> > * Add ide_id_dma_bug() helper based on ide_dma_verbose() to check for invalid
> >   DMA info in identify block.
> 
> > * Use ide_id_dma_bug() in ide_tune_dma() and ide_driveid_update().
> 
> >   As a result DMA won't be tuned or will be disabled after tuning if device
> >   reports inconsistent info about enabled DMA mode (ide_dma_verbose() does the
> >   same checks while the IDE device is probed by ide-{cd,disk} device driver).
> 
> > * Since (id->capability & 1) && id->tDMA is a valid configuration handle
> >   it correctly in ide_id_dma_bug().
> 
>     Huh? You don't check (id->capability & 1) there...
> 
> > * Remove no longer needed ide_dma_verbose().
> 
> > This patch should fix the following problem with out-of-sync IDE messages
> > reported by Nick Warne:
> 
> >        hdd: ATAPI 48X DVD-ROM DVD-R-RAM CD-R/RW drive, 2048kB Cache<7>hdd:
> >        skipping word 93 validity check
> >         , UDMA(66)
> 
> > and later debugged by Mark Lord to be caused by:
> 
> >         ide_dma_verbose()
> >                 printk( ... "2048kB Cache");
> >         eighty_ninty_three()
> >                 printk(KERN_DEBUG "%s: skipping word 93 validity check\n");
> >         ide_dma_verbose()
> >                 printk(", UDMA(66)"
> 
> > Please note that as a result ide-{cd,disk} device drivers won't report the
> > DMA speed used but this is intended since now DMA mode being used is always
> > reported by IDE core code.
> 
> > v2:
> > * fixes suggested by Randy:
> >   - use KERN_CONT for printk()-s in ide-{cd,disk}.c
> >   - don't remove argument name from ide_xfer_verbose() declaration
> 
> > Cc: Nick Warne <nick@ukfsn.org>
> > Cc: Mark Lord <lkml@rtr.ca>
> > Cc: Randy Dunlap <randy.dunlap@oracle.com>
> > Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
> 
> [...]
> 
> > Index: b/drivers/ide/ide-dma.c
> > ===================================================================
> > --- a/drivers/ide/ide-dma.c
> > +++ b/drivers/ide/ide-dma.c
> > @@ -806,58 +809,26 @@ static int ide_dma_check(ide_drive_t *dr
> >  	return vdma ? 0 : -1;
> >  }
> >  
> > -void ide_dma_verbose(ide_drive_t *drive)
> > +int ide_id_dma_bug(ide_drive_t *drive)
> >  {
> > -	struct hd_driveid *id	= drive->id;
> > -	ide_hwif_t *hwif	= HWIF(drive);
> > +	struct hd_driveid *id = drive->id;
> >  
> >  	if (id->field_valid & 4) {
> >  		if ((id->dma_ultra >> 8) && (id->dma_mword >> 8))
> [...]
> > +			goto err_out;
> >  	} else if (id->field_valid & 2) {
> >  		if ((id->dma_mword >> 8) && (id->dma_1word >> 8))
> > -			goto bug_dma_off;
> > -		printk(", DMA");
> > +			goto err_out;
> >  	} else if (id->field_valid & 1) {
> 
>     Hm, bit 0 only gurantees that current translation
> 
> > -		goto bug_dma_off;
> > +		if (id->tDMA == 0)
> 
>     Despite the name, this is not a transfer period but SW DMA mode number, so 
> why mode 0 is bad?

Thanks for checking the patch, I must have been half asleep while coding
this part cause it is completely bogus!

[ Well, it is not like that the code was OK before my changes... ;-) ]

I just removed incorrect (id->field_valid & 1) check in 'take 3'.

> > +			goto err_out;
> >  	}
> > -	return;
> > -bug_dma_off:
> > -	printk(", BUG DMA OFF");
> > -	hwif->dma_off_quietly(drive);
> > -	return;
> > +	return 0;
> > +err_out:
> > +	printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name);
> > +	return 1;
> >  }
> >  
> > Index: b/drivers/ide/ide-lib.c
> > ===================================================================
> > --- a/drivers/ide/ide-lib.c
> > +++ b/drivers/ide/ide-lib.c
> > @@ -29,41 +29,44 @@
> >   *	Add common non I/O op stuff here. Make sure it has proper
> >   *	kernel-doc function headers or your patch will be rejected
> >   */
> > - 
> > +
> > +static const char *udma_str[] =
> > +	 { "UDMA/16", "UDMA/25",  "UDMA/33",  "UDMA/44",
> > +	   "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
> > +static const char *mwdma_str[] =
> > +	{ "MWDMA0", "MWDMA1", "MWDMA2" };
> > +static const char *swdma_str[] =
> > +	{ "SWDMA0", "SWDMA1", "SWDMA2" };
> > +static const char *pio_str[] =
> > +	{ "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
> >  
> >  /**
> >   *	ide_xfer_verbose	-	return IDE mode names
> > - *	@xfer_rate: rate to name
> > + *	@mode: transfer mode
> >   *
> >   *	Returns a constant string giving the name of the mode
> >   *	requested.
> >   */
> >  
> > -char *ide_xfer_verbose (u8 xfer_rate)
> > +const char *ide_xfer_verbose(u8 mode)
> >  {
> [...]
> > +	const char *s;
> > +	u8 i = mode & 0xf;
> > +
> > +	if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
> > +		s = udma_str[i];
> > +	else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
> > +		s = mwdma_str[i];
> > +	else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
> > +		s = swdma_str[i];
> > +	else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
> > +		s = pio_str[i & 0x7];
> > +	else if (mode == XFER_PIO_SLOW)
> > +		s = "XFER SLOW";
> 
>     Not "PIO SLOW"?

fixed

While going through the patch I've noticed that ide_find_dma_mode() could
report the wrong mode for user requested and "CRC slow-down" speed changes,
this is also fixed now.

[PATCH] ide: DMA reporting and validity checking fixes (take 3)

* ide_xfer_verbose() fixups:
  - beautify returned mode names
  - fix PIO5 reporting
  - make it return 'const char *'

* Change printk() level from KERN_DEBUG to KERN_INFO in ide_find_dma_mode().

* Add ide_id_dma_bug() helper based on ide_dma_verbose() to check for invalid
  DMA info in identify block.

* Use ide_id_dma_bug() in ide_tune_dma() and ide_driveid_update().

  As a result DMA won't be tuned or will be disabled after tuning if device
  reports inconsistent info about enabled DMA mode (ide_dma_verbose() does the
  same checks while the IDE device is probed by ide-{cd,disk} device driver).

* Remove no longer needed ide_dma_verbose().

This patch should fix the following problem with out-of-sync IDE messages
reported by Nick Warne:

       hdd: ATAPI 48X DVD-ROM DVD-R-RAM CD-R/RW drive, 2048kB Cache<7>hdd:
       skipping word 93 validity check
        , UDMA(66)

and later debugged by Mark Lord to be caused by:

        ide_dma_verbose()
                printk( ... "2048kB Cache");
        eighty_ninty_three()
                printk(KERN_DEBUG "%s: skipping word 93 validity check\n");
        ide_dma_verbose()
                printk(", UDMA(66)"

Please note that as a result ide-{cd,disk} device drivers won't report the
DMA speed used but this is intended since now DMA mode being used is always
reported by IDE core code.

v2:
* fixes suggested by Randy:
  - use KERN_CONT for printk()-s in ide-{cd,disk}.c
  - don't remove argument name from ide_xfer_verbose() declaration

v3:
* Remove incorrect check for (id->field_valid & 1) from ide_id_dma_bug()
  (spotted by Sergei).

* "XFER SLOW" -> "PIO SLOW" in ide_xfer_verbose() (suggested by Sergei).

* Fix ide_find_dma_mode() to report the correct mode ('mode' after being
  limited by 'req_mode').

Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Cc: Nick Warne <nick@ukfsn.org>
Cc: Mark Lord <lkml@rtr.ca>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
---
 drivers/ide/ide-cd.c   |    7 -----
 drivers/ide/ide-disk.c |    7 +----
 drivers/ide/ide-dma.c  |   60 ++++++++++++-------------------------------------
 drivers/ide/ide-iops.c |    3 ++
 drivers/ide/ide-lib.c  |   55 +++++++++++++++++++++++---------------------
 include/linux/ide.h    |    6 ++--
 6 files changed, 53 insertions(+), 85 deletions(-)

Index: b/drivers/ide/ide-cd.c
===================================================================
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -3049,12 +3049,7 @@ int ide_cdrom_probe_capabilities (ide_dr
         else 	
         	printk(" drive");
 
-	printk(", %dkB Cache", be16_to_cpu(cap.buffer_size));
-
-	if (drive->using_dma)
-		ide_dma_verbose(drive);
-
-	printk("\n");
+	printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(cap.buffer_size));
 
 	return nslots;
 }
Index: b/drivers/ide/ide-disk.c
===================================================================
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -961,11 +961,8 @@ static void idedisk_setup (ide_drive_t *
 	if (id->buf_size)
 		printk (" w/%dKiB Cache", id->buf_size/2);
 
-	printk(", CHS=%d/%d/%d", 
-	       drive->bios_cyl, drive->bios_head, drive->bios_sect);
-	if (drive->using_dma)
-		ide_dma_verbose(drive);
-	printk("\n");
+	printk(KERN_CONT ", CHS=%d/%d/%d\n",
+			 drive->bios_cyl, drive->bios_head, drive->bios_sect);
 
 	/* write cache enabled? */
 	if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5)))
Index: b/drivers/ide/ide-dma.c
===================================================================
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -753,10 +753,12 @@ u8 ide_find_dma_mode(ide_drive_t *drive,
 			mode = XFER_MW_DMA_1;
 	}
 
-	printk(KERN_DEBUG "%s: %s mode selected\n", drive->name,
+	mode = min(mode, req_mode);
+
+	printk(KERN_INFO "%s: %s mode selected\n", drive->name,
 			  mode ? ide_xfer_verbose(mode) : "no DMA");
 
-	return min(mode, req_mode);
+	return mode;
 }
 
 EXPORT_SYMBOL_GPL(ide_find_dma_mode);
@@ -772,6 +774,9 @@ static int ide_tune_dma(ide_drive_t *dri
 	if (__ide_dma_bad_drive(drive))
 		return 0;
 
+	if (ide_id_dma_bug(drive))
+		return 0;
+
 	if (drive->hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
 		return config_drive_for_dma(drive);
 
@@ -806,58 +811,23 @@ static int ide_dma_check(ide_drive_t *dr
 	return vdma ? 0 : -1;
 }
 
-void ide_dma_verbose(ide_drive_t *drive)
+int ide_id_dma_bug(ide_drive_t *drive)
 {
-	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct hd_driveid *id = drive->id;
 
 	if (id->field_valid & 4) {
 		if ((id->dma_ultra >> 8) && (id->dma_mword >> 8))
-			goto bug_dma_off;
-		if (id->dma_ultra & ((id->dma_ultra >> 8) & hwif->ultra_mask)) {
-			if (((id->dma_ultra >> 11) & 0x1F) &&
-			    eighty_ninty_three(drive)) {
-				if ((id->dma_ultra >> 15) & 1) {
-					printk(", UDMA(mode 7)");
-				} else if ((id->dma_ultra >> 14) & 1) {
-					printk(", UDMA(133)");
-				} else if ((id->dma_ultra >> 13) & 1) {
-					printk(", UDMA(100)");
-				} else if ((id->dma_ultra >> 12) & 1) {
-					printk(", UDMA(66)");
-				} else if ((id->dma_ultra >> 11) & 1) {
-					printk(", UDMA(44)");
-				} else
-					goto mode_two;
-			} else {
-		mode_two:
-				if ((id->dma_ultra >> 10) & 1) {
-					printk(", UDMA(33)");
-				} else if ((id->dma_ultra >> 9) & 1) {
-					printk(", UDMA(25)");
-				} else if ((id->dma_ultra >> 8) & 1) {
-					printk(", UDMA(16)");
-				}
-			}
-		} else {
-			printk(", (U)DMA");	/* Can be BIOS-enabled! */
-		}
+			goto err_out;
 	} else if (id->field_valid & 2) {
 		if ((id->dma_mword >> 8) && (id->dma_1word >> 8))
-			goto bug_dma_off;
-		printk(", DMA");
-	} else if (id->field_valid & 1) {
-		goto bug_dma_off;
+			goto err_out;
 	}
-	return;
-bug_dma_off:
-	printk(", BUG DMA OFF");
-	hwif->dma_off_quietly(drive);
-	return;
+	return 0;
+err_out:
+	printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name);
+	return 1;
 }
 
-EXPORT_SYMBOL(ide_dma_verbose);
-
 int ide_set_dma(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
Index: b/drivers/ide/ide-iops.c
===================================================================
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -748,6 +748,9 @@ int ide_driveid_update(ide_drive_t *driv
 		drive->id->dma_1word = id->dma_1word;
 		/* anything more ? */
 		kfree(id);
+
+		if (drive->using_dma && ide_id_dma_bug(drive))
+			ide_dma_off(drive);
 	}
 
 	return 1;
Index: b/drivers/ide/ide-lib.c
===================================================================
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -29,41 +29,44 @@
  *	Add common non I/O op stuff here. Make sure it has proper
  *	kernel-doc function headers or your patch will be rejected
  */
- 
+
+static const char *udma_str[] =
+	 { "UDMA/16", "UDMA/25",  "UDMA/33",  "UDMA/44",
+	   "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
+static const char *mwdma_str[] =
+	{ "MWDMA0", "MWDMA1", "MWDMA2" };
+static const char *swdma_str[] =
+	{ "SWDMA0", "SWDMA1", "SWDMA2" };
+static const char *pio_str[] =
+	{ "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
 
 /**
  *	ide_xfer_verbose	-	return IDE mode names
- *	@xfer_rate: rate to name
+ *	@mode: transfer mode
  *
  *	Returns a constant string giving the name of the mode
  *	requested.
  */
 
-char *ide_xfer_verbose (u8 xfer_rate)
+const char *ide_xfer_verbose(u8 mode)
 {
-        switch(xfer_rate) {
-                case XFER_UDMA_7:	return("UDMA 7");
-                case XFER_UDMA_6:	return("UDMA 6");
-                case XFER_UDMA_5:	return("UDMA 5");
-                case XFER_UDMA_4:	return("UDMA 4");
-                case XFER_UDMA_3:	return("UDMA 3");
-                case XFER_UDMA_2:	return("UDMA 2");
-                case XFER_UDMA_1:	return("UDMA 1");
-                case XFER_UDMA_0:	return("UDMA 0");
-                case XFER_MW_DMA_2:	return("MW DMA 2");
-                case XFER_MW_DMA_1:	return("MW DMA 1");
-                case XFER_MW_DMA_0:	return("MW DMA 0");
-                case XFER_SW_DMA_2:	return("SW DMA 2");
-                case XFER_SW_DMA_1:	return("SW DMA 1");
-                case XFER_SW_DMA_0:	return("SW DMA 0");
-                case XFER_PIO_4:	return("PIO 4");
-                case XFER_PIO_3:	return("PIO 3");
-                case XFER_PIO_2:	return("PIO 2");
-                case XFER_PIO_1:	return("PIO 1");
-                case XFER_PIO_0:	return("PIO 0");
-                case XFER_PIO_SLOW:	return("PIO SLOW");
-                default:		return("XFER ERROR");
-        }
+	const char *s;
+	u8 i = mode & 0xf;
+
+	if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
+		s = udma_str[i];
+	else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
+		s = mwdma_str[i];
+	else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
+		s = swdma_str[i];
+	else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
+		s = pio_str[i & 0x7];
+	else if (mode == XFER_PIO_SLOW)
+		s = "PIO SLOW";
+	else
+		s = "XFER ERROR";
+
+	return s;
 }
 
 EXPORT_SYMBOL(ide_xfer_verbose);
Index: b/include/linux/ide.h
===================================================================
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1255,6 +1255,7 @@ int ide_in_drive_list(struct hd_driveid 
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 int __ide_dma_bad_drive(ide_drive_t *);
+int ide_id_dma_bug(ide_drive_t *);
 
 u8 ide_find_dma_mode(ide_drive_t *, u8);
 
@@ -1264,7 +1265,6 @@ static inline u8 ide_max_dma_mode(ide_dr
 }
 
 void ide_dma_off(ide_drive_t *);
-void ide_dma_verbose(ide_drive_t *);
 int ide_set_dma(ide_drive_t *);
 ide_startstop_t ide_dma_intr(ide_drive_t *);
 
@@ -1287,6 +1287,7 @@ extern void ide_dma_timeout(ide_drive_t 
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
 
 #else
+static inline int ide_id_dma_bug(ide_drive_t *drive) { return 0; }
 static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; }
 static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; }
 static inline void ide_dma_off(ide_drive_t *drive) { ; }
@@ -1333,8 +1334,7 @@ static inline void ide_set_hwifdata (ide
 	hwif->hwif_data = data;
 }
 
-/* ide-lib.c */
-extern char *ide_xfer_verbose(u8 xfer_rate);
+const char *ide_xfer_verbose(u8 mode);
 extern void ide_toggle_bounce(ide_drive_t *drive, int on);
 extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
 


  reply	other threads:[~2007-12-09 18:57 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-11-29 19:37 Peculiar out-of-sync boot log lines Nick Warne
2007-11-29 19:51 ` Jon Masters
2007-11-29 20:03   ` Nick Warne
2007-11-29 20:13     ` Joe Perches
2007-11-29 20:12 ` Mark Lord
2007-12-01 21:59   ` Bartlomiej Zolnierkiewicz
2007-12-01 23:14     ` Randy Dunlap
2007-12-02 18:30       ` Bartlomiej Zolnierkiewicz
2007-12-07 16:34         ` Sergei Shtylyov
2007-12-09 15:44           ` Bartlomiej Zolnierkiewicz [this message]
2007-12-23 17:30         ` Nick Warne
2007-12-02 17:31     ` Nick Warne
2007-12-02 18:34       ` Bartlomiej Zolnierkiewicz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200712091644.03448.bzolnier@gmail.com \
    --to=bzolnier@gmail.com \
    --cc=linux-ide@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lkml@rtr.ca \
    --cc=nick@ukfsn.org \
    --cc=randy.dunlap@oracle.com \
    --cc=sshtylyov@ru.mvista.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.