* [PATCH] libata: Fix a large collection of DMA mode mismatches
@ 2008-08-01 8:18 Alan Cox
2008-08-01 11:56 ` David Müller
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Alan Cox @ 2008-08-01 8:18 UTC (permalink / raw)
To: David Müller, jgarzik, linux-ide
From: Alan Cox <alan@redhat.com>
Dave Müller sent a diff for the pata_oldpiix that highlighted a problem
where a lot of the ATA drivers assume dma_mode == 0 means "no DMA" while
the core code uses 0xFF.
This turns out to have other consequences such as code doing >= XFER_UDMA_0
also catching 0xFF as UDMAlots. Fortunately it doesn't generally affect
set_dma_mode, although some drivers call back into their own set mode code
from other points.
Having been through the drivers I've added helpers for using_udma/using_mwdma
dma_enabled so that people don't open code ranges that may change (eg if UDMA8
appears somewhere)
Thanks to David for the initial bits
Signed-off-by: Alan Cox <alan@redhat.com>
---
drivers/ata/libata-core.c | 4 ++--
drivers/ata/pata_acpi.c | 2 +-
drivers/ata/pata_atiixp.c | 2 +-
drivers/ata/pata_cs5530.c | 6 +++---
drivers/ata/pata_sc1200.c | 6 +++---
include/linux/libata.h | 22 ++++++++++++++++++++++
6 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b4297ea..d7b6633 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -3267,7 +3267,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
dev->dma_mode = ata_xfer_mask2mode(dma_mask);
found = 1;
- if (dev->dma_mode != 0xff)
+ if (ata_dma_enabled(dev))
used_dma = 1;
}
if (!found)
@@ -3292,7 +3292,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
/* step 3: set host DMA timings */
ata_link_for_each_dev(dev, link) {
- if (!ata_dev_enabled(dev) || dev->dma_mode == 0xff)
+ if (!ata_dev_enabled(dev) || !ata_dma_enabled(dev))
continue;
dev->xfer_mode = dev->dma_mode;
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index c5f91e6..783e3c2 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -181,7 +181,7 @@ static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc)
if (adev != acpi->last) {
pacpi_set_piomode(ap, adev);
- if (adev->dma_mode)
+ if (ata_dma_enabled(adev))
pacpi_set_dmamode(ap, adev);
acpi->last = adev;
}
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index d7de7ba..e8a0d99 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -183,7 +183,7 @@ static void atiixp_bmdma_start(struct ata_queued_cmd *qc)
u16 tmp16;
pci_read_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
- if (adev->dma_mode >= XFER_UDMA_0)
+ if (ata_using_udma(adev))
tmp16 |= (1 << dn);
else
tmp16 &= ~(1 << dn);
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index 744beeb..0c4b271 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -149,10 +149,10 @@ static unsigned int cs5530_qc_issue(struct ata_queued_cmd *qc)
struct ata_device *prev = ap->private_data;
/* See if the DMA settings could be wrong */
- if (adev->dma_mode != 0 && adev != prev && prev != NULL) {
+ if (ata_dma_enabled(adev) && adev != prev && prev != NULL) {
/* Maybe, but do the channels match MWDMA/UDMA ? */
- if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) ||
- (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0))
+ if ((ata_using_udma(adev) && !ata_using_udma(prev)) ||
+ (ata_using_udma(prev) && !ata_using_udma(adev)))
/* Switch the mode bits */
cs5530_set_dmamode(ap, adev);
}
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index cbab397..0278fd2 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -167,10 +167,10 @@ static unsigned int sc1200_qc_issue(struct ata_queued_cmd *qc)
struct ata_device *prev = ap->private_data;
/* See if the DMA settings could be wrong */
- if (adev->dma_mode != 0 && adev != prev && prev != NULL) {
+ if (ata_dma_enabled(adev) && adev != prev && prev != NULL) {
/* Maybe, but do the channels match MWDMA/UDMA ? */
- if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) ||
- (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0))
+ if ((ata_using_udma(adev) && !ata_using_udma(prev)) ||
+ (ata_using_udma(prev) && !ata_using_udma(adev)))
/* Switch the mode bits */
sc1200_set_dmamode(ap, adev);
}
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 6820d6b..9bfe49e 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1427,6 +1427,28 @@ static inline unsigned long ata_deadline(unsigned long from_jiffies,
return from_jiffies + msecs_to_jiffies(timeout_msecs);
}
+/* Don't open code these in drivers as there are traps. Firstly the range may
+ change in future hardware and specs, secondly 0xFF means 'no DMA' but is
+ > UDMA_0. Dyma ddreigiau */
+
+static inline int ata_using_mwdma(struct ata_device *adev)
+{
+ if (adev->dma_mode >= XFER_MW_DMA_0 && adev->dma_mode <= XFER_MW_DMA_4)
+ return 1;
+ return 0;
+}
+
+static inline int ata_using_udma(struct ata_device *adev)
+{
+ if (adev->dma_mode >= XFER_UDMA_0 && adev->dma_mode <= XFER_UDMA_7)
+ return 1;
+ return 0;
+}
+
+static inline int ata_dma_enabled(struct ata_device *adev)
+{
+ return (adev->dma_mode == 0xFF ? 0 : 1);
+}
/**************************************************************************
* PMP - drivers/ata/libata-pmp.c
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] libata: Fix a large collection of DMA mode mismatches
2008-08-01 8:18 [PATCH] libata: Fix a large collection of DMA mode mismatches Alan Cox
@ 2008-08-01 11:56 ` David Müller
2008-08-01 22:42 ` Alan Cox
2008-08-03 4:45 ` Tejun Heo
2008-08-22 6:28 ` Jeff Garzik
2 siblings, 1 reply; 7+ messages in thread
From: David Müller @ 2008-08-01 11:56 UTC (permalink / raw)
To: Alan Cox; +Cc: jgarzik, linux-ide
Alan Cox wrote:
> drivers/ata/libata-core.c | 4 ++--
> drivers/ata/pata_acpi.c | 2 +-
> drivers/ata/pata_atiixp.c | 2 +-
> drivers/ata/pata_cs5530.c | 6 +++---
> drivers/ata/pata_sc1200.c | 6 +++---
> include/linux/libata.h | 22 ++++++++++++++++++++++
> 6 files changed, 32 insertions(+), 10 deletions(-)
A patch for the "pata_oldpiix" driver seems to be missing.
Signed-off-by: Dave Mueller <dave.mueller@gmx.ch>
diff -dpurN a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
--- a/drivers/ata/pata_oldpiix.c 2008-07-14 18:19:53.000000000 +0200
+++ b/drivers/ata/pata_oldpiix.c 2008-08-01 13:17:34.000000000 +0200
@@ -198,7 +198,7 @@ static unsigned int oldpiix_qc_issue(str
if (adev != ap->private_data) {
oldpiix_set_piomode(ap, adev);
- if (adev->dma_mode)
+ if (ata_dma_enabled(adev))
oldpiix_set_dmamode(ap, adev);
}
return ata_sff_qc_issue(qc);
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libata: Fix a large collection of DMA mode mismatches
2008-08-01 11:56 ` David Müller
@ 2008-08-01 22:42 ` Alan Cox
0 siblings, 0 replies; 7+ messages in thread
From: Alan Cox @ 2008-08-01 22:42 UTC (permalink / raw)
To: David Müller; +Cc: jgarzik, linux-ide
On Fri, 01 Aug 2008 13:56:56 +0200
David Müller <dave.mueller@gmx.ch> wrote:
> Alan Cox wrote:
> > drivers/ata/libata-core.c | 4 ++--
> > drivers/ata/pata_acpi.c | 2 +-
> > drivers/ata/pata_atiixp.c | 2 +-
> > drivers/ata/pata_cs5530.c | 6 +++---
> > drivers/ata/pata_sc1200.c | 6 +++---
> > include/linux/libata.h | 22 ++++++++++++++++++++++
> > 6 files changed, 32 insertions(+), 10 deletions(-)
>
> A patch for the "pata_oldpiix" driver seems to be missing.
>
> Signed-off-by: Dave Mueller <dave.mueller@gmx.ch>
Oops I meant to send that one on as well
Acked-by: Alan Cox <alan@redhat.com>
> diff -dpurN a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
> --- a/drivers/ata/pata_oldpiix.c 2008-07-14 18:19:53.000000000 +0200
> +++ b/drivers/ata/pata_oldpiix.c 2008-08-01 13:17:34.000000000 +0200
> @@ -198,7 +198,7 @@ static unsigned int oldpiix_qc_issue(str
>
> if (adev != ap->private_data) {
> oldpiix_set_piomode(ap, adev);
> - if (adev->dma_mode)
> + if (ata_dma_enabled(adev))
> oldpiix_set_dmamode(ap, adev);
> }
> return ata_sff_qc_issue(qc);
>
--
--
"Alan, I'm getting a bit worried about you."
-- Linus Torvalds
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libata: Fix a large collection of DMA mode mismatches
2008-08-01 8:18 [PATCH] libata: Fix a large collection of DMA mode mismatches Alan Cox
2008-08-01 11:56 ` David Müller
@ 2008-08-03 4:45 ` Tejun Heo
2008-08-03 13:08 ` Alan Cox
2008-08-22 6:28 ` Jeff Garzik
2 siblings, 1 reply; 7+ messages in thread
From: Tejun Heo @ 2008-08-03 4:45 UTC (permalink / raw)
To: Alan Cox; +Cc: David Müller, jgarzik, linux-ide
Hello, Alan.
Yeap, this approach looks much better. Just few nits.
Alan Cox wrote:
> @@ -1427,6 +1427,28 @@ static inline unsigned long ata_deadline(unsigned long from_jiffies,
> return from_jiffies + msecs_to_jiffies(timeout_msecs);
> }
>
> +/* Don't open code these in drivers as there are traps. Firstly the range may
> + change in future hardware and specs, secondly 0xFF means 'no DMA' but is
> + > UDMA_0. Dyma ddreigiau */
I suppose "Dyma ddreigiau" is just contamination? Also, can you please
use similar patch formatting as other comments for consistency?
> +static inline int ata_using_mwdma(struct ata_device *adev)
> +{
> + if (adev->dma_mode >= XFER_MW_DMA_0 && adev->dma_mode <= XFER_MW_DMA_4)
> + return 1;
> + return 0;
> +}
> +
> +static inline int ata_using_udma(struct ata_device *adev)
> +{
> + if (adev->dma_mode >= XFER_UDMA_0 && adev->dma_mode <= XFER_UDMA_7)
> + return 1;
> + return 0;
> +}
> +
> +static inline int ata_dma_enabled(struct ata_device *adev)
> +{
> + return (adev->dma_mode == 0xFF ? 0 : 1);
> +}
Wouldn't it be better to use ata_using_dma() instead like the other two?
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libata: Fix a large collection of DMA mode mismatches
2008-08-03 4:45 ` Tejun Heo
@ 2008-08-03 13:08 ` Alan Cox
2008-08-03 14:02 ` Tejun Heo
0 siblings, 1 reply; 7+ messages in thread
From: Alan Cox @ 2008-08-03 13:08 UTC (permalink / raw)
To: Tejun Heo; +Cc: David Müller, jgarzik, linux-ide
> > +/* Don't open code these in drivers as there are traps. Firstly the range may
> > + change in future hardware and specs, secondly 0xFF means 'no DMA' but is
> > + > UDMA_0. Dyma ddreigiau */
>
> I suppose "Dyma ddreigiau" is just contamination? Also, can you please
> use similar patch formatting as other comments for consistency?
No.. its essetially 'Here by Dragons', and to see if people actually read
patch comments 8)
> > +static inline int ata_dma_enabled(struct ata_device *adev)
> > +{
> > + return (adev->dma_mode == 0xFF ? 0 : 1);
> > +}
>
> Wouldn't it be better to use ata_using_dma() instead like the other two?
Not really fussed either way. Up to Jeff I guess.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libata: Fix a large collection of DMA mode mismatches
2008-08-03 13:08 ` Alan Cox
@ 2008-08-03 14:02 ` Tejun Heo
0 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2008-08-03 14:02 UTC (permalink / raw)
To: Alan Cox; +Cc: David Müller, jgarzik, linux-ide
Alan Cox wrote:
>>> +/* Don't open code these in drivers as there are traps. Firstly the range may
>>> + change in future hardware and specs, secondly 0xFF means 'no DMA' but is
>>> + > UDMA_0. Dyma ddreigiau */
>> I suppose "Dyma ddreigiau" is just contamination? Also, can you please
>> use similar patch formatting as other comments for consistency?
>
> No.. its essetially 'Here by Dragons', and to see if people actually read
> patch comments 8)
Ah.. Okay. English word games and Latin phrases scare me. :-)
>>> +static inline int ata_dma_enabled(struct ata_device *adev)
>>> +{
>>> + return (adev->dma_mode == 0xFF ? 0 : 1);
>>> +}
>> Wouldn't it be better to use ata_using_dma() instead like the other two?
>
> Not really fussed either way. Up to Jeff I guess.
The thing is ata_dma_enabled(dev) looks like it's testing whether the
device is capable of doing DMA while 'using' explicitly indicates the
current configuration. Well, no biggie either way.
--
tejun
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] libata: Fix a large collection of DMA mode mismatches
2008-08-01 8:18 [PATCH] libata: Fix a large collection of DMA mode mismatches Alan Cox
2008-08-01 11:56 ` David Müller
2008-08-03 4:45 ` Tejun Heo
@ 2008-08-22 6:28 ` Jeff Garzik
2 siblings, 0 replies; 7+ messages in thread
From: Jeff Garzik @ 2008-08-22 6:28 UTC (permalink / raw)
To: Alan Cox; +Cc: David Müller, linux-ide
Alan Cox wrote:
> From: Alan Cox <alan@redhat.com>
>
> Dave Müller sent a diff for the pata_oldpiix that highlighted a problem
> where a lot of the ATA drivers assume dma_mode == 0 means "no DMA" while
> the core code uses 0xFF.
>
> This turns out to have other consequences such as code doing >= XFER_UDMA_0
> also catching 0xFF as UDMAlots. Fortunately it doesn't generally affect
> set_dma_mode, although some drivers call back into their own set mode code
> from other points.
>
> Having been through the drivers I've added helpers for using_udma/using_mwdma
> dma_enabled so that people don't open code ranges that may change (eg if UDMA8
> appears somewhere)
>
> Thanks to David for the initial bits
>
> Signed-off-by: Alan Cox <alan@redhat.com>
> ---
>
> drivers/ata/libata-core.c | 4 ++--
> drivers/ata/pata_acpi.c | 2 +-
> drivers/ata/pata_atiixp.c | 2 +-
> drivers/ata/pata_cs5530.c | 6 +++---
> drivers/ata/pata_sc1200.c | 6 +++---
> include/linux/libata.h | 22 ++++++++++++++++++++++
> 6 files changed, 32 insertions(+), 10 deletions(-)
applied (w/ David's pata_oldpiix update)
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2008-08-22 6:28 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-01 8:18 [PATCH] libata: Fix a large collection of DMA mode mismatches Alan Cox
2008-08-01 11:56 ` David Müller
2008-08-01 22:42 ` Alan Cox
2008-08-03 4:45 ` Tejun Heo
2008-08-03 13:08 ` Alan Cox
2008-08-03 14:02 ` Tejun Heo
2008-08-22 6:28 ` Jeff Garzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).