Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ab7efe8 authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz
Browse files

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: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent e11b9035
Loading
Loading
Loading
Loading
+1 −6
Original line number Diff line number Diff line
@@ -3049,12 +3049,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
        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;
}
+2 −5
Original line number Diff line number Diff line
@@ -961,11 +961,8 @@ static void idedisk_setup (ide_drive_t *drive)
	if (id->buf_size)
		printk (" w/%dKiB Cache", id->buf_size/2);

	printk(", CHS=%d/%d/%d", 
	printk(KERN_CONT ", CHS=%d/%d/%d\n",
			 drive->bios_cyl, drive->bios_head, drive->bios_sect);
	if (drive->using_dma)
		ide_dma_verbose(drive);
	printk("\n");

	/* write cache enabled? */
	if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5)))
+15 −45
Original line number Diff line number Diff line
@@ -753,10 +753,12 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
			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 *drive)
	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 *drive)
	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);

	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;
+3 −0
Original line number Diff line number Diff line
@@ -748,6 +748,9 @@ int ide_driveid_update(ide_drive_t *drive)
		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;
+29 −26
Original line number Diff line number Diff line
@@ -30,40 +30,43 @@
 *	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);
Loading