2005-09-07 17:02:31

by Paul Fulghum

[permalink] [raw]
Subject: [patch] synclink.c compiler optimiation fix

[patch] synclink.c compiler optimization fix

From: Paul Fulghum <[email protected]>

Make some fields of DMA descriptor volatile to
prevent compiler optimizations.

Signed-off-by: Paul Fulghum <[email protected]>

--- linux-2.6.13/drivers/char/synclink.c 2005-09-07 11:43:56.000000000 -0500
+++ linux-2.6.13-mg/drivers/char/synclink.c 2005-09-07 11:52:08.000000000 -0500
@@ -1,7 +1,7 @@
/*
* linux/drivers/char/synclink.c
*
- * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $
+ * $Id: synclink.c,v 4.37 2005/09/07 13:13:19 paulkf Exp $
*
* Device driver for Microgate SyncLink ISA and PCI
* high speed multiprotocol serial adapters.
@@ -141,9 +141,9 @@ static MGSL_PARAMS default_params = {
typedef struct _DMABUFFERENTRY
{
u32 phys_addr; /* 32-bit flat physical address of data buffer */
- u16 count; /* buffer size/data count */
- u16 status; /* Control/status field */
- u16 rcc; /* character count field */
+ volatile u16 count; /* buffer size/data count */
+ volatile u16 status; /* Control/status field */
+ volatile u16 rcc; /* character count field */
u16 reserved; /* padding required by 16C32 */
u32 link; /* 32-bit flat link to next buffer entry */
char *virt_addr; /* virtual address of data buffer */
@@ -896,7 +896,7 @@ module_param_array(txdmabufs, int, NULL,
module_param_array(txholdbufs, int, NULL, 0);

static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.28 $";
+static char *driver_version = "$Revision: 4.37 $";

static int synclink_init_one (struct pci_dev *dev,
const struct pci_device_id *ent);



2005-09-08 13:52:18

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [patch] synclink.c compiler optimiation fix

On Wed, Sep 07, 2005 at 12:02:23PM -0500, Paul Fulghum wrote:
> - u16 count; /* buffer size/data count */
> - u16 status; /* Control/status field */
> - u16 rcc; /* character count field */
> + volatile u16 count; /* buffer size/data count */
> + volatile u16 status; /* Control/status field */
> + volatile u16 rcc; /* character count field */

this is wrong. The structure is in ioremaped memory so you must
use reads/writes to access them instead. volatile usage in drivers
is never okay - if you are accessing I/O memory you need to use
proper acessors, if it is normal memory and you want atomic sematics
you need to use the atomic_t type and the operators defined on it.

2005-09-08 15:33:15

by Paul Fulghum

[permalink] [raw]
Subject: Re: [patch] synclink.c compiler optimiation fix

Christoph Hellwig wrote:
> The structure is in ioremaped memory so you must
> use reads/writes to access them instead.

Yes, using read/write eliminates the compiler optimization
and makes the driver portable to other architectures.
That change is much more extensive, and it may be
a while before I can do a major rewrite of the driver.
The volatile change allows the existing driver to work.

> volatile usage in drivers
> is never okay - if you are accessing I/O memory you need to use
> proper acessors, if it is normal memory and you want atomic sematics
> you need to use the atomic_t type and the operators defined on it.

This is not a matter of atomicity.
It is a matter of hardware DMA causing the
value to change without the compiler's knowledge.

If I have a DMA descriptor in normal memory (not the
case in the above driver, but it is the case in
another driver I maintain) that has fields that
do not conform to atomic_t, using volatile seems
a valid way of preventing the compiler from
optimizing access to the field out of a loop.

--
Paul Fulghum
Microgate Systems, Ltd.