public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
To: Andrew Morton <akpm@osdl.org>
Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>,
	Linux IDE <linux-ide@vger.kernel.org>,
	LKML <linux-kernel@vger.kernel.org>
Subject: [PATCH] ide_dma_speed() fixes
Date: Fri, 12 May 2006 06:36:56 +0400	[thread overview]
Message-ID: <4463F4C8.9080608@ru.mvista.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 416 bytes --]

Hello.

    ide_dma_speed() fails to actually honor the IDE drivers' mode support 
masks) because of the bogus checks -- thus, selecting the DMA transfer mode 
that the driver explicitly refuses to support is possible. Additionally, there 
is no check for validity of the UltraDMA mode data in the drive ID, and the 
function is misdocumented.

MBR, Sergei

Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>


[-- Attachment #2: ide_dma_speed-fix.patch --]
[-- Type: text/plain, Size: 3165 bytes --]

Index: linus/drivers/ide/ide-lib.c
===================================================================
--- linus.orig/drivers/ide/ide-lib.c
+++ linus/drivers/ide/ide-lib.c
@@ -72,66 +72,65 @@ EXPORT_SYMBOL(ide_xfer_verbose);
 /**
  *	ide_dma_speed	-	compute DMA speed
  *	@drive: drive
- *	@mode; intended mode
+ *	@mode:	modes available
  *
  *	Checks the drive capabilities and returns the speed to use
- *	for the transfer. Returns -1 if the requested mode is unknown
- *	(eg PIO)
+ *	for the DMA transfer.  Returns 0 if the drive is incapable
+ *	of DMA transfers.
  */
  
 u8 ide_dma_speed(ide_drive_t *drive, u8 mode)
 {
 	struct hd_driveid *id   = drive->id;
 	ide_hwif_t *hwif	= HWIF(drive);
+	u8 ultra_mask, mwdma_mask, swdma_mask;
 	u8 speed = 0;
 
 	if (drive->media != ide_disk && hwif->atapi_dma == 0)
 		return 0;
 
-	switch(mode) {
-		case 0x04:
-			if ((id->dma_ultra & 0x0040) &&
-			    (id->dma_ultra & hwif->ultra_mask))
+	/* Capable of UltraDMA modes? */
+	if (id->field_valid & 4)
+		ultra_mask = id->dma_ultra & hwif->ultra_mask;
+	else
+		mode = 0;	/* fallback to MW/SW DMA if no UltraDMA */
+
+	switch (mode) {
+		case 4:
+			if (ultra_mask & 0x40)
 				{ speed = XFER_UDMA_6; break; }
-		case 0x03:
-			if ((id->dma_ultra & 0x0020) &&
-			    (id->dma_ultra & hwif->ultra_mask))
+		case 3:
+			if (ultra_mask & 0x20)
 				{ speed = XFER_UDMA_5; break; }
-		case 0x02:
-			if ((id->dma_ultra & 0x0010) &&
-			    (id->dma_ultra & hwif->ultra_mask))
+		case 2:
+			if (ultra_mask & 0x10)
 				{ speed = XFER_UDMA_4; break; }
-			if ((id->dma_ultra & 0x0008) &&
-			    (id->dma_ultra & hwif->ultra_mask))
+			if (ultra_mask & 0x08)
 				{ speed = XFER_UDMA_3; break; }
-		case 0x01:
-			if ((id->dma_ultra & 0x0004) &&
-			    (id->dma_ultra & hwif->ultra_mask))
+		case 1:
+			if (ultra_mask & 0x04)
 				{ speed = XFER_UDMA_2; break; }
-			if ((id->dma_ultra & 0x0002) &&
-			    (id->dma_ultra & hwif->ultra_mask))
+			if (ultra_mask & 0x02)
 				{ speed = XFER_UDMA_1; break; }
-			if ((id->dma_ultra & 0x0001) &&
-			    (id->dma_ultra & hwif->ultra_mask))
+			if (ultra_mask & 0x01)
 				{ speed = XFER_UDMA_0; break; }
-		case 0x00:
-			if ((id->dma_mword & 0x0004) &&
-			    (id->dma_mword & hwif->mwdma_mask))
+		case 0:
+			mwdma_mask = id->dma_mword & hwif->mwdma_mask;
+
+			if (mwdma_mask & 0x04)
 				{ speed = XFER_MW_DMA_2; break; }
-			if ((id->dma_mword & 0x0002) &&
-			    (id->dma_mword & hwif->mwdma_mask))
+			if (mwdma_mask & 0x02)
 				{ speed = XFER_MW_DMA_1; break; }
-			if ((id->dma_mword & 0x0001) &&
-			    (id->dma_mword & hwif->mwdma_mask))
+			if (mwdma_mask & 0x01)
 				{ speed = XFER_MW_DMA_0; break; }
-			if ((id->dma_1word & 0x0004) &&
-			    (id->dma_1word & hwif->swdma_mask))
+
+			swdma_mask = id->dma_1word & hwif->swdma_mask;
+
+			if (swdma_mask & 0x04)
 				{ speed = XFER_SW_DMA_2; break; }
-			if ((id->dma_1word & 0x0002) &&
-			    (id->dma_1word & hwif->swdma_mask))
+			if (swdma_mask & 0x02)
 				{ speed = XFER_SW_DMA_1; break; }
-			if ((id->dma_1word & 0x0001) &&
-			    (id->dma_1word & hwif->swdma_mask))
+			if (swdma_mask & 0x01)
 				{ speed = XFER_SW_DMA_0; break; }
 	}
 

             reply	other threads:[~2006-05-12  2:38 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-05-12  2:36 Sergei Shtylyov [this message]
2006-05-14 12:05 ` [PATCH] ide_dma_speed() fixes Andrew Morton
2006-05-15 13:44   ` Sergei Shtylyov
2006-05-15 14:08     ` Alan Cox
2006-05-15 15:00     ` Andrew Morton
2006-05-15 15:27       ` Alan Cox

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=4463F4C8.9080608@ru.mvista.com \
    --to=sshtylyov@ru.mvista.com \
    --cc=akpm@osdl.org \
    --cc=bzolnier@gmail.com \
    --cc=linux-ide@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox