2005-01-24 14:09:37

by Ian Campbell

[permalink] [raw]
Subject: RFC: use datacs is smc91x driver

Hi Nico,

Below is a first cut at supporting the second 32-bit DATACS chipselect
in the smc91x driver to transfer data.

My platform has a 16-bit chip select for the primary IO region and no
DMA. I found that throughput went from roughly 50mbit/s to 80mbit/s. I
tested by throwing UDP packets at it using mgen (9000 packets/second
with UDP payload of 1472 bytes is roughly 100mbit/s, I think) and
counting the packets received in 60s, I then did the same for
transmitting. The measurements are very rough but the improvement seems
fairly significant to me. Perhaps there is another benchmark you would
like me to try?

I did consider adding a define for 'NEEDS_ATTRIB_ENABLE' but decided not
to in the end for backwards compat, and because I have no platforms to
test that bit on. That is why the attrib stuff has been factored out of
smc_probe(), I think it is tidier that way anyway.

I'm not entirely happy with using the SMC_*_RESOURCE defines to find the
correct resources, but I don't think you can have a placeholder for the
attrib space at index 1 (when you don't have an attrib space) and still
have datacs at index 2.

What do you think?

Ian.

Signed-off-by: Ian Campbell <[email protected]>

Index: 2.6/drivers/net/smc91x.c
===================================================================
--- 2.6.orig/drivers/net/smc91x.c 2005-01-24 10:22:49.000000000 +0000
+++ 2.6/drivers/net/smc91x.c 2005-01-24 11:58:13.543739813 +0000
@@ -201,6 +201,10 @@

spinlock_t lock;

+#ifdef SMC_CAN_USE_DATACS
+ u32 *datacs;
+#endif
+
#ifdef SMC_USE_PXA_DMA
/* DMA needs the physical address of the chip */
u_long physaddr;
@@ -1989,16 +1993,21 @@
return retval;
}

-static int smc_enable_device(unsigned long attrib_phys)
+static int smc_enable_device(struct platform_device *pdev)
{
unsigned long flags;
unsigned char ecor, ecsr;
void *addr;
+ struct resource * res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, SMC_ATTRIB_RESOURCE);
+ if (!res)
+ return 0;

/*
* Map the attribute space. This is overkill, but clean.
*/
- addr = ioremap(attrib_phys, ATTRIB_SIZE);
+ addr = ioremap(res->start, ATTRIB_SIZE);
if (!addr)
return -ENOMEM;

@@ -2046,6 +2055,72 @@
return 0;
}

+static int smc_request_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource(pdev, IORESOURCE_MEM, SMC_ATTRIB_RESOURCE);
+
+ if (res) {
+ if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME))
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static void smc_release_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource(pdev, IORESOURCE_MEM, SMC_ATTRIB_RESOURCE);
+
+ if (res)
+ release_mem_region(res->start, ATTRIB_SIZE);
+}
+
+#ifdef SMC_CAN_USE_DATACS
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct resource * res = platform_get_resource(pdev, IORESOURCE_MEM, SMC_DATACS_RESOURCE);
+ struct smc_local *lp = netdev_priv(ndev);
+
+ if (!res) {
+ printk(KERN_CRIT "no datacs resource\n");
+ return;
+ }
+
+ if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) {
+ printk(KERN_CRIT "failed request region\n");
+ return;
+ }
+
+ printk(KERN_CRIT "%s: requested datacs memory region %#010lx-%#010lx\n",
+ CARDNAME, res->start, res->end);
+
+ lp->datacs = ioremap(res->start, SMC_DATA_EXTENT);
+ printk(KERN_CRIT "%s: remapped datacs to %p\n", CARDNAME, lp->datacs);
+
+}
+
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct smc_local *lp = netdev_priv(ndev);
+ struct resource * res = platform_get_resource(pdev, IORESOURCE_MEM, SMC_DATACS_RESOURCE);
+
+ if (lp->datacs) {
+ printk(KERN_CRIT "%s: releasing datacs at %p\n", CARDNAME, lp->datacs);
+ iounmap(lp->datacs);
+ }
+
+ lp->datacs = NULL;
+
+ if (res) {
+ release_mem_region(res->start, SMC_DATA_EXTENT);
+ printk(KERN_CRIT "%s: released datacs memory region %#010lx-%#010lx\n",
+ CARDNAME, res->start, res->end);
+ }
+}
+#else
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+#endif
+
/*
* smc_init(void)
* Input parameters:
@@ -2061,20 +2136,18 @@
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev;
- struct resource *res, *ext = NULL;
+ struct resource *res;
unsigned int *addr;
int ret;

- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, SMC_IO_RESOURCE);
if (!res) {
ret = -ENODEV;
goto out;
}

- /*
- * Request the regions.
- */
- if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
+
+ if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
ret = -EBUSY;
goto out;
}
@@ -2083,7 +2156,7 @@
if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
- goto release_1;
+ goto out_release_io;
}
SET_MODULE_OWNER(ndev);
SET_NETDEV_DEV(ndev, dev);
@@ -2091,42 +2164,27 @@
ndev->dma = (unsigned char)-1;
ndev->irq = platform_get_irq(pdev, 0);

- ext = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (ext) {
- if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) {
- ret = -EBUSY;
- goto release_1;
- }
-
+ ret = smc_request_attrib(pdev);
+ if (ret)
+ goto out_free_netdev;
#if defined(CONFIG_SA1100_ASSABET)
- NCR_0 |= NCR_ENET_OSC_EN;
+ NCR_0 |= NCR_ENET_OSC_EN;
#endif
-
- ret = smc_enable_device(ext->start);
- if (ret)
- goto release_both;
- }
+ ret = smc_enable_device(pdev);
+ if (ret)
+ goto out_release_attrib;

addr = ioremap(res->start, SMC_IO_EXTENT);
if (!addr) {
ret = -ENOMEM;
- goto release_both;
+ goto out_release_attrib;
}
+ printk(KERN_CRIT "%s: mapped IO to %p\n", CARDNAME, addr);

dev_set_drvdata(dev, ndev);
ret = smc_probe(ndev, (unsigned long)addr);
- if (ret != 0) {
- dev_set_drvdata(dev, NULL);
- iounmap(addr);
- release_both:
- if (ext)
- release_mem_region(ext->start, ATTRIB_SIZE);
- free_netdev(ndev);
- release_1:
- release_mem_region(res->start, SMC_IO_EXTENT);
- out:
- printk("%s: not found (%d).\n", CARDNAME, ret);
- }
+ if (ret != 0)
+ goto out_iounmap;
#ifdef SMC_USE_PXA_DMA
else {
struct smc_local *lp = netdev_priv(ndev);
@@ -2134,6 +2192,22 @@
}
#endif

+ smc_request_datacs(pdev, ndev);
+
+ return 0;
+
+ out_iounmap:
+ dev_set_drvdata(dev, NULL);
+ iounmap(addr);
+ out_release_attrib:
+ smc_release_attrib(pdev);
+ out_free_netdev:
+ free_netdev(ndev);
+ out_release_io:
+ release_mem_region(res->start, SMC_IO_EXTENT);
+ out:
+ printk("%s: not found (%d).\n", CARDNAME, ret);
+
return ret;
}

@@ -2154,10 +2228,11 @@
pxa_free_dma(ndev->dma);
#endif
iounmap((void *)ndev->base_addr);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res)
- release_mem_region(res->start, ATTRIB_SIZE);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ smc_release_datacs(pdev,ndev);
+ smc_release_attrib(pdev);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, SMC_IO_RESOURCE);
release_mem_region(res->start, SMC_IO_EXTENT);

free_netdev(ndev);
@@ -2186,9 +2261,7 @@

if (ndev && level == RESUME_ENABLE) {
struct smc_local *lp = netdev_priv(ndev);
-
- if (pdev->num_resources == 3)
- smc_enable_device(pdev->resource[2].start);
+ smc_enable_device(pdev);
if (netif_running(ndev)) {
smc_reset(ndev);
smc_enable(ndev);
Index: 2.6/drivers/net/smc91x.h
===================================================================
--- 2.6.orig/drivers/net/smc91x.h 2005-01-24 10:22:49.000000000 +0000
+++ 2.6/drivers/net/smc91x.h 2005-01-24 11:36:35.297811106 +0000
@@ -380,7 +381,16 @@
#define SMC_IO_SHIFT 0
#endif
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
+#define SMC_DATA_EXTENT (4)

+#define SMC_IO_RESOURCE 0
+
+#if defined (SMC_CAN_USE_DATACS)
+# define SMC_DATACS_RESOURCE 1
+# define SMC_ATTRIB_RESOURCE 2
+#else
+# define SMC_ATTRIB_RESOURCE 1
+#endif

/*
. Bank Select Register:
@@ -901,7 +911,7 @@
#endif

#if SMC_CAN_USE_32BIT
-#define SMC_PUSH_DATA(p, l) \
+#define _SMC_PUSH_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -916,7 +926,7 @@
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \
} while (0)
-#define SMC_PULL_DATA(p, l) \
+#define _SMC_PULL_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -936,11 +946,11 @@
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
} while (0)
#elif SMC_CAN_USE_16BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#elif SMC_CAN_USE_8BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
-#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
+#define _SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
+#define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#endif

#if ! SMC_CAN_USE_16BIT
@@ -959,6 +969,51 @@
})
#endif

+#if SMC_CAN_USE_DATACS
+#define SMC_PUSH_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if (__len >= 2 && (unsigned long)__ptr & 2) { \
+ __len -= 2; \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ __ptr += 2; \
+ } \
+ outsl(lp->datacs, __ptr, __len >> 2); \
+ if (__len & 2) { \
+ __ptr += (__len & ~3); \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ } \
+ } else { \
+ _SMC_PUSH_DATA(p, l); \
+ }
+
+#define SMC_PULL_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if ((unsigned long)__ptr & 2) { \
+ /* \
+ * We want 32bit alignment here. \
+ * Since some buses perform a full 32bit \
+ * fetch even for 16bit data we can't use \
+ * SMC_inw() here. Back both source (on chip \
+ * and destination) pointers of 2 bytes. \
+ */ \
+ __ptr -= 2; \
+ __len += 2; \
+ SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
+ } \
+ __len += 2; \
+ insl( lp->datacs, __ptr, __len >> 2); \
+ } else { \
+ _SMC_PULL_DATA(p, l); \
+ }
+#else
+#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
+#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
+#endif
+
#if !defined (SMC_INTERRUPT_PREAMBLE)
# define SMC_INTERRUPT_PREAMBLE
#endif



--
Ian Campbell, Senior Design Engineer
Web: http://www.arcom.com
Arcom, Clifton Road, Direct: +44 (0)1223 403 465
Cambridge CB1 7EA, United Kingdom Phone: +44 (0)1223 411 200


_____________________________________________________________________
The message in this transmission is sent in confidence for the attention of the addressee only and should not be disclosed to any other party. Unauthorised recipients are requested to preserve this confidentiality. Please advise the sender if the addressee is not resident at the receiving end. Email to and from Arcom is automatically monitored for operational and lawful business reasons.

This message has been virus scanned by MessageLabs.


2005-01-24 20:22:48

by Nicolas Pitre

[permalink] [raw]
Subject: Re: RFC: use datacs is smc91x driver

On Mon, 24 Jan 2005, Ian Campbell wrote:

> Hi Nico,
>
> Below is a first cut at supporting the second 32-bit DATACS chipselect
> in the smc91x driver to transfer data.

[...]

> I'm not entirely happy with using the SMC_*_RESOURCE defines to find the
> correct resources, but I don't think you can have a placeholder for the
> attrib space at index 1 (when you don't have an attrib space) and still
> have datacs at index 2.

I don't like that either. Maybe the whole thing should be converted to
use platform_get_resource_byname() ?


Nicolas

2005-01-25 11:14:23

by Ian Campbell

[permalink] [raw]
Subject: Re: RFC: use datacs is smc91x driver

On Mon, 2005-01-24 at 15:20 -0500, Nicolas Pitre wrote:
> On Mon, 24 Jan 2005, Ian Campbell wrote:
> > I'm not entirely happy with using the SMC_*_RESOURCE defines to find the
> > correct resources, but I don't think you can have a placeholder for the
> > attrib space at index 1 (when you don't have an attrib space) and still
> > have datacs at index 2.
>
> I don't like that either. Maybe the whole thing should be converted to
> use platform_get_resource_byname() ?

Ah, I hadn't seen this new function, it looks ideal. I'll work up
another that uses it and updates all the in tree drivers.

Are you happy with "iocs", "attrib" and "datacs" for the names?

Ian.

--
Ian Campbell, Senior Design Engineer
Web: http://www.arcom.com
Arcom, Clifton Road, Direct: +44 (0)1223 403 465
Cambridge CB1 7EA, United Kingdom Phone: +44 (0)1223 411 200


_____________________________________________________________________
The message in this transmission is sent in confidence for the attention of the addressee only and should not be disclosed to any other party. Unauthorised recipients are requested to preserve this confidentiality. Please advise the sender if the addressee is not resident at the receiving end. Email to and from Arcom is automatically monitored for operational and lawful business reasons.

This message has been virus scanned by MessageLabs.

2005-01-25 15:10:10

by Ian Campbell

[permalink] [raw]
Subject: Re: RFC: use datacs is smc91x driver

On Tue, 2005-01-25 at 11:14 +0000, Ian Campbell wrote:
> Are you happy with "iocs", "attrib" and "datacs" for the names?

Of the platforms with an smc91x platform_device (according to grep) only
2 (lubbock, neponset) out of the 18 have memory resources other than the
iocs (full list of platforms is at the end, after the patch)

So for the sake of the least intrusive patch I think for the main iocs
I'll call _byname and fallback on mem resource number 0 if no named iocs
resource exists. attrib and datacs must be explicitly named. This allows
most of the board ports to remain unchanged.

I also noticed that the name propagates into /proc/iomem etc
# cat /proc/iomem
[...]
10000000-10000003 : datacs
10000000-10000003 : smc91x
so perhaps smc91x-datacs -attrib -iocs might be more appropriate names?
I don't know if there is a policy about such things.

Signed-off-by: Ian Campbell <[email protected]>

Index: 2.6/drivers/net/smc91x.c
===================================================================
--- 2.6.orig/drivers/net/smc91x.c 2005-01-25 08:48:28.000000000 +0000
+++ 2.6/drivers/net/smc91x.c 2005-01-25 14:47:42.281379016 +0000
@@ -210,6 +210,10 @@

spinlock_t lock;

+#ifdef SMC_CAN_USE_DATACS
+ u32 *datacs;
+#endif
+
#ifdef SMC_USE_PXA_DMA
/* DMA needs the physical address of the chip */
u_long physaddr;
@@ -1998,16 +2002,21 @@
return retval;
}

-static int smc_enable_device(unsigned long attrib_phys)
+static int smc_enable_device(struct platform_device *pdev)
{
unsigned long flags;
unsigned char ecor, ecsr;
void *addr;
+ struct resource * res;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "attrib");
+ if (!res)
+ return 0;

/*
* Map the attribute space. This is overkill, but clean.
*/
- addr = ioremap(attrib_phys, ATTRIB_SIZE);
+ addr = ioremap(res->start, ATTRIB_SIZE);
if (!addr)
return -ENOMEM;

@@ -2055,6 +2064,62 @@
return 0;
}

+static int smc_request_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "attrib");
+
+ if (!res)
+ return 0;
+
+ if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME))
+ return -EBUSY;
+
+ return 0;
+}
+
+static void smc_release_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "attrib");
+
+ if (res)
+ release_mem_region(res->start, ATTRIB_SIZE);
+}
+
+#ifdef SMC_CAN_USE_DATACS
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "datacs");
+ struct smc_local *lp = netdev_priv(ndev);
+
+ if (!res)
+ return;
+
+ if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) {
+ printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME);
+ return;
+ }
+
+ lp->datacs = ioremap(res->start, SMC_DATA_EXTENT);
+}
+
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct smc_local *lp = netdev_priv(ndev);
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "datacs");
+
+ if (lp->datacs)
+ iounmap(lp->datacs);
+
+ lp->datacs = NULL;
+
+ if (res)
+ release_mem_region(res->start, SMC_DATA_EXTENT);
+}
+#else
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+#endif
+
/*
* smc_init(void)
* Input parameters:
@@ -2070,20 +2135,20 @@
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev;
- struct resource *res, *ext = NULL;
+ struct resource *res;
unsigned int *addr;
int ret;

- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iocs");
+ if (!res)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
goto out;
}

- /*
- * Request the regions.
- */
- if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
+
+ if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
ret = -EBUSY;
goto out;
}
@@ -2092,7 +2157,7 @@
if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
- goto release_1;
+ goto out_release_io;
}
SET_MODULE_OWNER(ndev);
SET_NETDEV_DEV(ndev, dev);
@@ -2100,42 +2165,26 @@
ndev->dma = (unsigned char)-1;
ndev->irq = platform_get_irq(pdev, 0);

- ext = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (ext) {
- if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) {
- ret = -EBUSY;
- goto release_1;
- }
-
+ ret = smc_request_attrib(pdev);
+ if (ret)
+ goto out_free_netdev;
#if defined(CONFIG_SA1100_ASSABET)
- NCR_0 |= NCR_ENET_OSC_EN;
+ NCR_0 |= NCR_ENET_OSC_EN;
#endif
-
- ret = smc_enable_device(ext->start);
- if (ret)
- goto release_both;
- }
+ ret = smc_enable_device(pdev);
+ if (ret)
+ goto out_release_attrib;

addr = ioremap(res->start, SMC_IO_EXTENT);
if (!addr) {
ret = -ENOMEM;
- goto release_both;
+ goto out_release_attrib;
}

dev_set_drvdata(dev, ndev);
ret = smc_probe(ndev, (unsigned long)addr);
- if (ret != 0) {
- dev_set_drvdata(dev, NULL);
- iounmap(addr);
- release_both:
- if (ext)
- release_mem_region(ext->start, ATTRIB_SIZE);
- free_netdev(ndev);
- release_1:
- release_mem_region(res->start, SMC_IO_EXTENT);
- out:
- printk("%s: not found (%d).\n", CARDNAME, ret);
- }
+ if (ret != 0)
+ goto out_iounmap;
#ifdef SMC_USE_PXA_DMA
else {
struct smc_local *lp = netdev_priv(ndev);
@@ -2143,6 +2192,22 @@
}
#endif

+ smc_request_datacs(pdev, ndev);
+
+ return 0;
+
+ out_iounmap:
+ dev_set_drvdata(dev, NULL);
+ iounmap(addr);
+ out_release_attrib:
+ smc_release_attrib(pdev);
+ out_free_netdev:
+ free_netdev(ndev);
+ out_release_io:
+ release_mem_region(res->start, SMC_IO_EXTENT);
+ out:
+ printk("%s: not found (%d).\n", CARDNAME, ret);
+
return ret;
}

@@ -2163,10 +2228,13 @@
pxa_free_dma(ndev->dma);
#endif
iounmap((void *)ndev->base_addr);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res)
- release_mem_region(res->start, ATTRIB_SIZE);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ smc_release_datacs(pdev,ndev);
+ smc_release_attrib(pdev);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iocs");
+ if (!res)
+ platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, SMC_IO_EXTENT);

free_netdev(ndev);
@@ -2195,9 +2263,7 @@

if (ndev && level == RESUME_ENABLE) {
struct smc_local *lp = netdev_priv(ndev);
-
- if (pdev->num_resources == 3)
- smc_enable_device(pdev->resource[2].start);
+ smc_enable_device(pdev);
if (netif_running(ndev)) {
smc_reset(ndev);
smc_enable(ndev);
Index: 2.6/drivers/net/smc91x.h
===================================================================
--- 2.6.orig/drivers/net/smc91x.h 2005-01-04 14:11:08.000000000 +0000
+++ 2.6/drivers/net/smc91x.h 2005-01-25 14:47:42.363356954 +0000
@@ -362,7 +362,7 @@
#define SMC_IO_SHIFT 0
#endif
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
-
+#define SMC_DATA_EXTENT (4)

/*
. Bank Select Register:
@@ -883,7 +883,7 @@
#endif

#if SMC_CAN_USE_32BIT
-#define SMC_PUSH_DATA(p, l) \
+#define _SMC_PUSH_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -898,7 +898,7 @@
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \
} while (0)
-#define SMC_PULL_DATA(p, l) \
+#define _SMC_PULL_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -918,11 +918,11 @@
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
} while (0)
#elif SMC_CAN_USE_16BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#elif SMC_CAN_USE_8BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
-#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
+#define _SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
+#define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#endif

#if ! SMC_CAN_USE_16BIT
@@ -941,6 +941,51 @@
})
#endif

+#if SMC_CAN_USE_DATACS
+#define SMC_PUSH_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if (__len >= 2 && (unsigned long)__ptr & 2) { \
+ __len -= 2; \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ __ptr += 2; \
+ } \
+ outsl(lp->datacs, __ptr, __len >> 2); \
+ if (__len & 2) { \
+ __ptr += (__len & ~3); \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ } \
+ } else { \
+ _SMC_PUSH_DATA(p, l); \
+ }
+
+#define SMC_PULL_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if ((unsigned long)__ptr & 2) { \
+ /* \
+ * We want 32bit alignment here. \
+ * Since some buses perform a full 32bit \
+ * fetch even for 16bit data we can't use \
+ * SMC_inw() here. Back both source (on chip \
+ * and destination) pointers of 2 bytes. \
+ */ \
+ __ptr -= 2; \
+ __len += 2; \
+ SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
+ } \
+ __len += 2; \
+ insl( lp->datacs, __ptr, __len >> 2); \
+ } else { \
+ _SMC_PULL_DATA(p, l); \
+ }
+#else
+#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
+#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
+#endif
+
#if !defined (SMC_INTERRUPT_PREAMBLE)
# define SMC_INTERRUPT_PREAMBLE
#endif
Index: 2.6/arch/arm/mach-sa1100/neponset.c
===================================================================
--- 2.6.orig/arch/arm/mach-sa1100/neponset.c 2005-01-04 14:10:53.000000000 +0000
+++ 2.6/arch/arm/mach-sa1100/neponset.c 2005-01-25 14:47:42.119422603 +0000
@@ -266,6 +266,7 @@

static struct resource smc91x_resources[] = {
[0] = {
+ .name = "iocs",
.start = SA1100_CS3_PHYS,
.end = SA1100_CS3_PHYS + 0x01ffffff,
.flags = IORESOURCE_MEM,
@@ -276,6 +277,7 @@
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = "attrib",
.start = SA1100_CS3_PHYS + 0x02000000,
.end = SA1100_CS3_PHYS + 0x03ffffff,
.flags = IORESOURCE_MEM,
Index: 2.6/arch/arm/mach-pxa/lubbock.c
===================================================================
--- 2.6.orig/arch/arm/mach-pxa/lubbock.c 2005-01-04 14:10:53.000000000 +0000
+++ 2.6/arch/arm/mach-pxa/lubbock.c 2005-01-25 14:47:42.042443321 +0000
@@ -137,6 +137,7 @@

static struct resource smc91x_resources[] = {
[0] = {
+ .name = "iocs",
.start = 0x0c000000,
.end = 0x0c0fffff,
.flags = IORESOURCE_MEM,
@@ -147,6 +148,7 @@
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = "attrib",
.start = 0x0e000000,
.end = 0x0e0fffff,
.flags = IORESOURCE_MEM,


Files declaring an smc91x platform device:
arch/ppc/platforms/4xx/redwood5.c
arch/ppc/platforms/4xx/redwood6.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-sa1100/pleb.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-lh7a40x/arch-lpd7a40x.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-versatile/core.c
arch/arm/mach-omap/board-innovator.c
arch/arm/mach-omap/board-h3.c
arch/arm/mach-omap/board-perseus2.c
arch/arm/mach-omap/board-osk.c
arch/arm/mach-omap/board-h2.c
arch/sh/boards/superh/microdev/setup.c
arch/m32r/kernel/setup_opsput.c
arch/m32r/kernel/setup_mappi2.c
arch/m32r/kernel/setup_m32700ut.c


--
Ian Campbell, Senior Design Engineer
Web: http://www.arcom.com
Arcom, Clifton Road, Direct: +44 (0)1223 403 465
Cambridge CB1 7EA, United Kingdom Phone: +44 (0)1223 411 200

2005-01-25 15:43:14

by Nicolas Pitre

[permalink] [raw]
Subject: Re: RFC: use datacs is smc91x driver

On Tue, 25 Jan 2005, Ian Campbell wrote:

> On Tue, 2005-01-25 at 11:14 +0000, Ian Campbell wrote:
> > Are you happy with "iocs", "attrib" and "datacs" for the names?
>
> Of the platforms with an smc91x platform_device (according to grep) only
> 2 (lubbock, neponset) out of the 18 have memory resources other than the
> iocs (full list of platforms is at the end, after the patch)
>
> So for the sake of the least intrusive patch I think for the main iocs
> I'll call _byname and fallback on mem resource number 0 if no named iocs
> resource exists. attrib and datacs must be explicitly named. This allows
> most of the board ports to remain unchanged.

Sensible.

> I also noticed that the name propagates into /proc/iomem etc
> # cat /proc/iomem
> [...]
> 10000000-10000003 : datacs
> 10000000-10000003 : smc91x
> so perhaps smc91x-datacs -attrib -iocs might be more appropriate names?

Probably, although "iocs" is rather criptic for someone not familiar
with the chip. What about "smc91x-regs", "smc91x-attrib" and
"smc91x-data32" ?


Nicolas

2005-01-25 16:26:29

by Ian Campbell

[permalink] [raw]
Subject: Re: RFC: use datacs is smc91x driver

On Tue, 2005-01-25 at 10:41 -0500, Nicolas Pitre wrote:
> On Tue, 25 Jan 2005, Ian Campbell wrote:
> > so perhaps smc91x-datacs -attrib -iocs might be more appropriate names?
>
> Probably, although "iocs" is rather criptic for someone not familiar
> with the chip. What about "smc91x-regs", "smc91x-attrib" and
> "smc91x-data32" ?

Sounds good. Are you happy for me to send the version below to Andrew
and Jeff for inclusion? compiled on lubbock and neponset, compiled and
tested on my platform.

Cheers,
Ian.

Signed-off-by: Ian Campbell <[email protected]>

Index: 2.6/drivers/net/smc91x.c
===================================================================
--- 2.6.orig/drivers/net/smc91x.c 2005-01-25 08:48:28.000000000 +0000
+++ 2.6/drivers/net/smc91x.c 2005-01-25 15:56:00.405373349 +0000
@@ -210,6 +210,10 @@

spinlock_t lock;

+#ifdef SMC_CAN_USE_DATACS
+ u32 *datacs;
+#endif
+
#ifdef SMC_USE_PXA_DMA
/* DMA needs the physical address of the chip */
u_long physaddr;
@@ -1998,16 +2002,21 @@
return retval;
}

-static int smc_enable_device(unsigned long attrib_phys)
+static int smc_enable_device(struct platform_device *pdev)
{
unsigned long flags;
unsigned char ecor, ecsr;
void *addr;
+ struct resource * res;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+ if (!res)
+ return 0;

/*
* Map the attribute space. This is overkill, but clean.
*/
- addr = ioremap(attrib_phys, ATTRIB_SIZE);
+ addr = ioremap(res->start, ATTRIB_SIZE);
if (!addr)
return -ENOMEM;

@@ -2055,6 +2064,62 @@
return 0;
}

+static int smc_request_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+
+ if (!res)
+ return 0;
+
+ if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME))
+ return -EBUSY;
+
+ return 0;
+}
+
+static void smc_release_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+
+ if (res)
+ release_mem_region(res->start, ATTRIB_SIZE);
+}
+
+#ifdef SMC_CAN_USE_DATACS
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
+ struct smc_local *lp = netdev_priv(ndev);
+
+ if (!res)
+ return;
+
+ if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) {
+ printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME);
+ return;
+ }
+
+ lp->datacs = ioremap(res->start, SMC_DATA_EXTENT);
+}
+
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct smc_local *lp = netdev_priv(ndev);
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
+
+ if (lp->datacs)
+ iounmap(lp->datacs);
+
+ lp->datacs = NULL;
+
+ if (res)
+ release_mem_region(res->start, SMC_DATA_EXTENT);
+}
+#else
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+#endif
+
/*
* smc_init(void)
* Input parameters:
@@ -2070,20 +2135,20 @@
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev;
- struct resource *res, *ext = NULL;
+ struct resource *res;
unsigned int *addr;
int ret;

- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
goto out;
}

- /*
- * Request the regions.
- */
- if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
+
+ if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
ret = -EBUSY;
goto out;
}
@@ -2092,7 +2157,7 @@
if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
- goto release_1;
+ goto out_release_io;
}
SET_MODULE_OWNER(ndev);
SET_NETDEV_DEV(ndev, dev);
@@ -2100,42 +2165,26 @@
ndev->dma = (unsigned char)-1;
ndev->irq = platform_get_irq(pdev, 0);

- ext = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (ext) {
- if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) {
- ret = -EBUSY;
- goto release_1;
- }
-
+ ret = smc_request_attrib(pdev);
+ if (ret)
+ goto out_free_netdev;
#if defined(CONFIG_SA1100_ASSABET)
- NCR_0 |= NCR_ENET_OSC_EN;
+ NCR_0 |= NCR_ENET_OSC_EN;
#endif
-
- ret = smc_enable_device(ext->start);
- if (ret)
- goto release_both;
- }
+ ret = smc_enable_device(pdev);
+ if (ret)
+ goto out_release_attrib;

addr = ioremap(res->start, SMC_IO_EXTENT);
if (!addr) {
ret = -ENOMEM;
- goto release_both;
+ goto out_release_attrib;
}

dev_set_drvdata(dev, ndev);
ret = smc_probe(ndev, (unsigned long)addr);
- if (ret != 0) {
- dev_set_drvdata(dev, NULL);
- iounmap(addr);
- release_both:
- if (ext)
- release_mem_region(ext->start, ATTRIB_SIZE);
- free_netdev(ndev);
- release_1:
- release_mem_region(res->start, SMC_IO_EXTENT);
- out:
- printk("%s: not found (%d).\n", CARDNAME, ret);
- }
+ if (ret != 0)
+ goto out_iounmap;
#ifdef SMC_USE_PXA_DMA
else {
struct smc_local *lp = netdev_priv(ndev);
@@ -2143,6 +2192,22 @@
}
#endif

+ smc_request_datacs(pdev, ndev);
+
+ return 0;
+
+ out_iounmap:
+ dev_set_drvdata(dev, NULL);
+ iounmap(addr);
+ out_release_attrib:
+ smc_release_attrib(pdev);
+ out_free_netdev:
+ free_netdev(ndev);
+ out_release_io:
+ release_mem_region(res->start, SMC_IO_EXTENT);
+ out:
+ printk("%s: not found (%d).\n", CARDNAME, ret);
+
return ret;
}

@@ -2163,10 +2228,13 @@
pxa_free_dma(ndev->dma);
#endif
iounmap((void *)ndev->base_addr);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res)
- release_mem_region(res->start, ATTRIB_SIZE);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ smc_release_datacs(pdev,ndev);
+ smc_release_attrib(pdev);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+ platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, SMC_IO_EXTENT);

free_netdev(ndev);
@@ -2195,9 +2263,7 @@

if (ndev && level == RESUME_ENABLE) {
struct smc_local *lp = netdev_priv(ndev);
-
- if (pdev->num_resources == 3)
- smc_enable_device(pdev->resource[2].start);
+ smc_enable_device(pdev);
if (netif_running(ndev)) {
smc_reset(ndev);
smc_enable(ndev);
Index: 2.6/drivers/net/smc91x.h
===================================================================
--- 2.6.orig/drivers/net/smc91x.h 2005-01-04 14:11:08.000000000 +0000
+++ 2.6/drivers/net/smc91x.h 2005-01-25 14:47:42.000000000 +0000
@@ -362,7 +362,7 @@
#define SMC_IO_SHIFT 0
#endif
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
-
+#define SMC_DATA_EXTENT (4)

/*
. Bank Select Register:
@@ -883,7 +883,7 @@
#endif

#if SMC_CAN_USE_32BIT
-#define SMC_PUSH_DATA(p, l) \
+#define _SMC_PUSH_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -898,7 +898,7 @@
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \
} while (0)
-#define SMC_PULL_DATA(p, l) \
+#define _SMC_PULL_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -918,11 +918,11 @@
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
} while (0)
#elif SMC_CAN_USE_16BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#elif SMC_CAN_USE_8BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
-#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
+#define _SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
+#define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#endif

#if ! SMC_CAN_USE_16BIT
@@ -941,6 +941,51 @@
})
#endif

+#if SMC_CAN_USE_DATACS
+#define SMC_PUSH_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if (__len >= 2 && (unsigned long)__ptr & 2) { \
+ __len -= 2; \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ __ptr += 2; \
+ } \
+ outsl(lp->datacs, __ptr, __len >> 2); \
+ if (__len & 2) { \
+ __ptr += (__len & ~3); \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ } \
+ } else { \
+ _SMC_PUSH_DATA(p, l); \
+ }
+
+#define SMC_PULL_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if ((unsigned long)__ptr & 2) { \
+ /* \
+ * We want 32bit alignment here. \
+ * Since some buses perform a full 32bit \
+ * fetch even for 16bit data we can't use \
+ * SMC_inw() here. Back both source (on chip \
+ * and destination) pointers of 2 bytes. \
+ */ \
+ __ptr -= 2; \
+ __len += 2; \
+ SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
+ } \
+ __len += 2; \
+ insl( lp->datacs, __ptr, __len >> 2); \
+ } else { \
+ _SMC_PULL_DATA(p, l); \
+ }
+#else
+#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
+#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
+#endif
+
#if !defined (SMC_INTERRUPT_PREAMBLE)
# define SMC_INTERRUPT_PREAMBLE
#endif
Index: 2.6/arch/arm/mach-sa1100/neponset.c
===================================================================
--- 2.6.orig/arch/arm/mach-sa1100/neponset.c 2005-01-04 14:10:53.000000000 +0000
+++ 2.6/arch/arm/mach-sa1100/neponset.c 2005-01-25 15:56:00.130447587 +0000
@@ -266,6 +266,7 @@

static struct resource smc91x_resources[] = {
[0] = {
+ .name = "smc91x-regs",
.start = SA1100_CS3_PHYS,
.end = SA1100_CS3_PHYS + 0x01ffffff,
.flags = IORESOURCE_MEM,
@@ -276,6 +277,7 @@
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = "smc91x-attrib",
.start = SA1100_CS3_PHYS + 0x02000000,
.end = SA1100_CS3_PHYS + 0x03ffffff,
.flags = IORESOURCE_MEM,
Index: 2.6/arch/arm/mach-pxa/lubbock.c
===================================================================
--- 2.6.orig/arch/arm/mach-pxa/lubbock.c 2005-01-04 14:10:53.000000000 +0000
+++ 2.6/arch/arm/mach-pxa/lubbock.c 2005-01-25 15:56:00.048469724 +0000
@@ -137,6 +137,7 @@

static struct resource smc91x_resources[] = {
[0] = {
+ .name = "smc91x-regs",
.start = 0x0c000000,
.end = 0x0c0fffff,
.flags = IORESOURCE_MEM,
@@ -147,6 +148,7 @@
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = "smc91x-attrib",
.start = 0x0e000000,
.end = 0x0e0fffff,
.flags = IORESOURCE_MEM,



--
Ian Campbell, Senior Design Engineer
Web: http://www.arcom.com
Arcom, Clifton Road, Direct: +44 (0)1223 403 465
Cambridge CB1 7EA, United Kingdom Phone: +44 (0)1223 411 200


_____________________________________________________________________
The message in this transmission is sent in confidence for the attention of the addressee only and should not be disclosed to any other party. Unauthorised recipients are requested to preserve this confidentiality. Please advise the sender if the addressee is not resident at the receiving end. Email to and from Arcom is automatically monitored for operational and lawful business reasons.

This message has been virus scanned by MessageLabs.

2005-01-25 16:51:43

by Nicolas Pitre

[permalink] [raw]
Subject: Re: RFC: use datacs is smc91x driver

On Tue, 25 Jan 2005, Ian Campbell wrote:

> Sounds good. Are you happy for me to send the version below to Andrew
> and Jeff for inclusion? compiled on lubbock and neponset, compiled and
> tested on my platform.
>
> Cheers,
> Ian.
>
> Signed-off-by: Ian Campbell <[email protected]>

Signed-off-by: Nicolas Pitre <[email protected]>


>
> Index: 2.6/drivers/net/smc91x.c
> ===================================================================
> --- 2.6.orig/drivers/net/smc91x.c 2005-01-25 08:48:28.000000000 +0000
> +++ 2.6/drivers/net/smc91x.c 2005-01-25 15:56:00.405373349 +0000
> @@ -210,6 +210,10 @@
>
> spinlock_t lock;
>
> +#ifdef SMC_CAN_USE_DATACS
> + u32 *datacs;
> +#endif
> +
> #ifdef SMC_USE_PXA_DMA
> /* DMA needs the physical address of the chip */
> u_long physaddr;
> @@ -1998,16 +2002,21 @@
> return retval;
> }
>
> -static int smc_enable_device(unsigned long attrib_phys)
> +static int smc_enable_device(struct platform_device *pdev)
> {
> unsigned long flags;
> unsigned char ecor, ecsr;
> void *addr;
> + struct resource * res;
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
> + if (!res)
> + return 0;
>
> /*
> * Map the attribute space. This is overkill, but clean.
> */
> - addr = ioremap(attrib_phys, ATTRIB_SIZE);
> + addr = ioremap(res->start, ATTRIB_SIZE);
> if (!addr)
> return -ENOMEM;
>
> @@ -2055,6 +2064,62 @@
> return 0;
> }
>
> +static int smc_request_attrib(struct platform_device *pdev)
> +{
> + struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
> +
> + if (!res)
> + return 0;
> +
> + if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME))
> + return -EBUSY;
> +
> + return 0;
> +}
> +
> +static void smc_release_attrib(struct platform_device *pdev)
> +{
> + struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
> +
> + if (res)
> + release_mem_region(res->start, ATTRIB_SIZE);
> +}
> +
> +#ifdef SMC_CAN_USE_DATACS
> +static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev)
> +{
> + struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
> + struct smc_local *lp = netdev_priv(ndev);
> +
> + if (!res)
> + return;
> +
> + if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) {
> + printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME);
> + return;
> + }
> +
> + lp->datacs = ioremap(res->start, SMC_DATA_EXTENT);
> +}
> +
> +static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev)
> +{
> + struct smc_local *lp = netdev_priv(ndev);
> + struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
> +
> + if (lp->datacs)
> + iounmap(lp->datacs);
> +
> + lp->datacs = NULL;
> +
> + if (res)
> + release_mem_region(res->start, SMC_DATA_EXTENT);
> +}
> +#else
> +static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) {}
> +static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) {}
> +#endif
> +
> /*
> * smc_init(void)
> * Input parameters:
> @@ -2070,20 +2135,20 @@
> {
> struct platform_device *pdev = to_platform_device(dev);
> struct net_device *ndev;
> - struct resource *res, *ext = NULL;
> + struct resource *res;
> unsigned int *addr;
> int ret;
>
> - res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
> + if (!res)
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> if (!res) {
> ret = -ENODEV;
> goto out;
> }
>
> - /*
> - * Request the regions.
> - */
> - if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
> +
> + if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
> ret = -EBUSY;
> goto out;
> }
> @@ -2092,7 +2157,7 @@
> if (!ndev) {
> printk("%s: could not allocate device.\n", CARDNAME);
> ret = -ENOMEM;
> - goto release_1;
> + goto out_release_io;
> }
> SET_MODULE_OWNER(ndev);
> SET_NETDEV_DEV(ndev, dev);
> @@ -2100,42 +2165,26 @@
> ndev->dma = (unsigned char)-1;
> ndev->irq = platform_get_irq(pdev, 0);
>
> - ext = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> - if (ext) {
> - if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) {
> - ret = -EBUSY;
> - goto release_1;
> - }
> -
> + ret = smc_request_attrib(pdev);
> + if (ret)
> + goto out_free_netdev;
> #if defined(CONFIG_SA1100_ASSABET)
> - NCR_0 |= NCR_ENET_OSC_EN;
> + NCR_0 |= NCR_ENET_OSC_EN;
> #endif
> -
> - ret = smc_enable_device(ext->start);
> - if (ret)
> - goto release_both;
> - }
> + ret = smc_enable_device(pdev);
> + if (ret)
> + goto out_release_attrib;
>
> addr = ioremap(res->start, SMC_IO_EXTENT);
> if (!addr) {
> ret = -ENOMEM;
> - goto release_both;
> + goto out_release_attrib;
> }
>
> dev_set_drvdata(dev, ndev);
> ret = smc_probe(ndev, (unsigned long)addr);
> - if (ret != 0) {
> - dev_set_drvdata(dev, NULL);
> - iounmap(addr);
> - release_both:
> - if (ext)
> - release_mem_region(ext->start, ATTRIB_SIZE);
> - free_netdev(ndev);
> - release_1:
> - release_mem_region(res->start, SMC_IO_EXTENT);
> - out:
> - printk("%s: not found (%d).\n", CARDNAME, ret);
> - }
> + if (ret != 0)
> + goto out_iounmap;
> #ifdef SMC_USE_PXA_DMA
> else {
> struct smc_local *lp = netdev_priv(ndev);
> @@ -2143,6 +2192,22 @@
> }
> #endif
>
> + smc_request_datacs(pdev, ndev);
> +
> + return 0;
> +
> + out_iounmap:
> + dev_set_drvdata(dev, NULL);
> + iounmap(addr);
> + out_release_attrib:
> + smc_release_attrib(pdev);
> + out_free_netdev:
> + free_netdev(ndev);
> + out_release_io:
> + release_mem_region(res->start, SMC_IO_EXTENT);
> + out:
> + printk("%s: not found (%d).\n", CARDNAME, ret);
> +
> return ret;
> }
>
> @@ -2163,10 +2228,13 @@
> pxa_free_dma(ndev->dma);
> #endif
> iounmap((void *)ndev->base_addr);
> - res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> - if (res)
> - release_mem_region(res->start, ATTRIB_SIZE);
> - res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> + smc_release_datacs(pdev,ndev);
> + smc_release_attrib(pdev);
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
> + if (!res)
> + platform_get_resource(pdev, IORESOURCE_MEM, 0);
> release_mem_region(res->start, SMC_IO_EXTENT);
>
> free_netdev(ndev);
> @@ -2195,9 +2263,7 @@
>
> if (ndev && level == RESUME_ENABLE) {
> struct smc_local *lp = netdev_priv(ndev);
> -
> - if (pdev->num_resources == 3)
> - smc_enable_device(pdev->resource[2].start);
> + smc_enable_device(pdev);
> if (netif_running(ndev)) {
> smc_reset(ndev);
> smc_enable(ndev);
> Index: 2.6/drivers/net/smc91x.h
> ===================================================================
> --- 2.6.orig/drivers/net/smc91x.h 2005-01-04 14:11:08.000000000 +0000
> +++ 2.6/drivers/net/smc91x.h 2005-01-25 14:47:42.000000000 +0000
> @@ -362,7 +362,7 @@
> #define SMC_IO_SHIFT 0
> #endif
> #define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
> -
> +#define SMC_DATA_EXTENT (4)
>
> /*
> . Bank Select Register:
> @@ -883,7 +883,7 @@
> #endif
>
> #if SMC_CAN_USE_32BIT
> -#define SMC_PUSH_DATA(p, l) \
> +#define _SMC_PUSH_DATA(p, l) \
> do { \
> char *__ptr = (p); \
> int __len = (l); \
> @@ -898,7 +898,7 @@
> SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
> } \
> } while (0)
> -#define SMC_PULL_DATA(p, l) \
> +#define _SMC_PULL_DATA(p, l) \
> do { \
> char *__ptr = (p); \
> int __len = (l); \
> @@ -918,11 +918,11 @@
> SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
> } while (0)
> #elif SMC_CAN_USE_16BIT
> -#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
> -#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
> +#define _SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
> +#define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
> #elif SMC_CAN_USE_8BIT
> -#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
> -#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
> +#define _SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
> +#define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
> #endif
>
> #if ! SMC_CAN_USE_16BIT
> @@ -941,6 +941,51 @@
> })
> #endif
>
> +#if SMC_CAN_USE_DATACS
> +#define SMC_PUSH_DATA(p, l) \
> + if ( lp->datacs ) { \
> + unsigned char *__ptr = (p); \
> + int __len = (l); \
> + if (__len >= 2 && (unsigned long)__ptr & 2) { \
> + __len -= 2; \
> + SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
> + __ptr += 2; \
> + } \
> + outsl(lp->datacs, __ptr, __len >> 2); \
> + if (__len & 2) { \
> + __ptr += (__len & ~3); \
> + SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
> + } \
> + } else { \
> + _SMC_PUSH_DATA(p, l); \
> + }
> +
> +#define SMC_PULL_DATA(p, l) \
> + if ( lp->datacs ) { \
> + unsigned char *__ptr = (p); \
> + int __len = (l); \
> + if ((unsigned long)__ptr & 2) { \
> + /* \
> + * We want 32bit alignment here. \
> + * Since some buses perform a full 32bit \
> + * fetch even for 16bit data we can't use \
> + * SMC_inw() here. Back both source (on chip \
> + * and destination) pointers of 2 bytes. \
> + */ \
> + __ptr -= 2; \
> + __len += 2; \
> + SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
> + } \
> + __len += 2; \
> + insl( lp->datacs, __ptr, __len >> 2); \
> + } else { \
> + _SMC_PULL_DATA(p, l); \
> + }
> +#else
> +#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
> +#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
> +#endif
> +
> #if !defined (SMC_INTERRUPT_PREAMBLE)
> # define SMC_INTERRUPT_PREAMBLE
> #endif
> Index: 2.6/arch/arm/mach-sa1100/neponset.c
> ===================================================================
> --- 2.6.orig/arch/arm/mach-sa1100/neponset.c 2005-01-04 14:10:53.000000000 +0000
> +++ 2.6/arch/arm/mach-sa1100/neponset.c 2005-01-25 15:56:00.130447587 +0000
> @@ -266,6 +266,7 @@
>
> static struct resource smc91x_resources[] = {
> [0] = {
> + .name = "smc91x-regs",
> .start = SA1100_CS3_PHYS,
> .end = SA1100_CS3_PHYS + 0x01ffffff,
> .flags = IORESOURCE_MEM,
> @@ -276,6 +277,7 @@
> .flags = IORESOURCE_IRQ,
> },
> [2] = {
> + .name = "smc91x-attrib",
> .start = SA1100_CS3_PHYS + 0x02000000,
> .end = SA1100_CS3_PHYS + 0x03ffffff,
> .flags = IORESOURCE_MEM,
> Index: 2.6/arch/arm/mach-pxa/lubbock.c
> ===================================================================
> --- 2.6.orig/arch/arm/mach-pxa/lubbock.c 2005-01-04 14:10:53.000000000 +0000
> +++ 2.6/arch/arm/mach-pxa/lubbock.c 2005-01-25 15:56:00.048469724 +0000
> @@ -137,6 +137,7 @@
>
> static struct resource smc91x_resources[] = {
> [0] = {
> + .name = "smc91x-regs",
> .start = 0x0c000000,
> .end = 0x0c0fffff,
> .flags = IORESOURCE_MEM,
> @@ -147,6 +148,7 @@
> .flags = IORESOURCE_IRQ,
> },
> [2] = {
> + .name = "smc91x-attrib",
> .start = 0x0e000000,
> .end = 0x0e0fffff,
> .flags = IORESOURCE_MEM,
>
>
>
> --
> Ian Campbell, Senior Design Engineer
> Web: http://www.arcom.com
> Arcom, Clifton Road, Direct: +44 (0)1223 403 465
> Cambridge CB1 7EA, United Kingdom Phone: +44 (0)1223 411 200
>
>
> _____________________________________________________________________
> The message in this transmission is sent in confidence for the attention of the addressee only and should not be disclosed to any other party. Unauthorised recipients are requested to preserve this confidentiality. Please advise the sender if the addressee is not resident at the receiving end. Email to and from Arcom is automatically monitored for operational and lawful business reasons.
>
> This message has been virus scanned by MessageLabs.
>


Nicolas

2005-01-25 17:07:57

by Ian Campbell

[permalink] [raw]
Subject: [PATCH] use datacs is smc91x driver

Hi,

Below is a patch to support the second 32-bit DATACS chipselect
in the smc91x driver to transfer data. Support is enabled by adding a
resource to the platform device named 'smc91x-data32'.

My platform has a 16-bit chip select for the primary IO region and no
DMA. I found that throughput went from roughly 50mbit/s to 80mbit/s. I
tested by throwing UDP packets at it using mgen (9000 packets/second
with UDP payload of 1472 bytes is roughly 100mbit/s, I think) and
counting the packets received in 60s, I then did the same for
transmitting. The measurements are very rough but the improvement seems
fairly significant to me.

Patch was compiled for lubbock and neponset and compiled and tested on
my PXA platform.

Signed-off-by: Ian Campbell <[email protected]>
Signed-off-by: Nicolas Pitre <[email protected]>

Index: 2.6/drivers/net/smc91x.c
===================================================================
--- 2.6.orig/drivers/net/smc91x.c 2005-01-25 08:48:28.000000000 +0000
+++ 2.6/drivers/net/smc91x.c 2005-01-25 15:56:00.405373349 +0000
@@ -210,6 +210,10 @@

spinlock_t lock;

+#ifdef SMC_CAN_USE_DATACS
+ u32 *datacs;
+#endif
+
#ifdef SMC_USE_PXA_DMA
/* DMA needs the physical address of the chip */
u_long physaddr;
@@ -1998,16 +2002,21 @@
return retval;
}

-static int smc_enable_device(unsigned long attrib_phys)
+static int smc_enable_device(struct platform_device *pdev)
{
unsigned long flags;
unsigned char ecor, ecsr;
void *addr;
+ struct resource * res;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+ if (!res)
+ return 0;

/*
* Map the attribute space. This is overkill, but clean.
*/
- addr = ioremap(attrib_phys, ATTRIB_SIZE);
+ addr = ioremap(res->start, ATTRIB_SIZE);
if (!addr)
return -ENOMEM;

@@ -2055,6 +2064,62 @@
return 0;
}

+static int smc_request_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+
+ if (!res)
+ return 0;
+
+ if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME))
+ return -EBUSY;
+
+ return 0;
+}
+
+static void smc_release_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+
+ if (res)
+ release_mem_region(res->start, ATTRIB_SIZE);
+}
+
+#ifdef SMC_CAN_USE_DATACS
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
+ struct smc_local *lp = netdev_priv(ndev);
+
+ if (!res)
+ return;
+
+ if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) {
+ printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME);
+ return;
+ }
+
+ lp->datacs = ioremap(res->start, SMC_DATA_EXTENT);
+}
+
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct smc_local *lp = netdev_priv(ndev);
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
+
+ if (lp->datacs)
+ iounmap(lp->datacs);
+
+ lp->datacs = NULL;
+
+ if (res)
+ release_mem_region(res->start, SMC_DATA_EXTENT);
+}
+#else
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+#endif
+
/*
* smc_init(void)
* Input parameters:
@@ -2070,20 +2135,20 @@
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev;
- struct resource *res, *ext = NULL;
+ struct resource *res;
unsigned int *addr;
int ret;

- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
goto out;
}

- /*
- * Request the regions.
- */
- if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
+
+ if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
ret = -EBUSY;
goto out;
}
@@ -2092,7 +2157,7 @@
if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
- goto release_1;
+ goto out_release_io;
}
SET_MODULE_OWNER(ndev);
SET_NETDEV_DEV(ndev, dev);
@@ -2100,42 +2165,26 @@
ndev->dma = (unsigned char)-1;
ndev->irq = platform_get_irq(pdev, 0);

- ext = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (ext) {
- if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) {
- ret = -EBUSY;
- goto release_1;
- }
-
+ ret = smc_request_attrib(pdev);
+ if (ret)
+ goto out_free_netdev;
#if defined(CONFIG_SA1100_ASSABET)
- NCR_0 |= NCR_ENET_OSC_EN;
+ NCR_0 |= NCR_ENET_OSC_EN;
#endif
-
- ret = smc_enable_device(ext->start);
- if (ret)
- goto release_both;
- }
+ ret = smc_enable_device(pdev);
+ if (ret)
+ goto out_release_attrib;

addr = ioremap(res->start, SMC_IO_EXTENT);
if (!addr) {
ret = -ENOMEM;
- goto release_both;
+ goto out_release_attrib;
}

dev_set_drvdata(dev, ndev);
ret = smc_probe(ndev, (unsigned long)addr);
- if (ret != 0) {
- dev_set_drvdata(dev, NULL);
- iounmap(addr);
- release_both:
- if (ext)
- release_mem_region(ext->start, ATTRIB_SIZE);
- free_netdev(ndev);
- release_1:
- release_mem_region(res->start, SMC_IO_EXTENT);
- out:
- printk("%s: not found (%d).\n", CARDNAME, ret);
- }
+ if (ret != 0)
+ goto out_iounmap;
#ifdef SMC_USE_PXA_DMA
else {
struct smc_local *lp = netdev_priv(ndev);
@@ -2143,6 +2192,22 @@
}
#endif

+ smc_request_datacs(pdev, ndev);
+
+ return 0;
+
+ out_iounmap:
+ dev_set_drvdata(dev, NULL);
+ iounmap(addr);
+ out_release_attrib:
+ smc_release_attrib(pdev);
+ out_free_netdev:
+ free_netdev(ndev);
+ out_release_io:
+ release_mem_region(res->start, SMC_IO_EXTENT);
+ out:
+ printk("%s: not found (%d).\n", CARDNAME, ret);
+
return ret;
}

@@ -2163,10 +2228,13 @@
pxa_free_dma(ndev->dma);
#endif
iounmap((void *)ndev->base_addr);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res)
- release_mem_region(res->start, ATTRIB_SIZE);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ smc_release_datacs(pdev,ndev);
+ smc_release_attrib(pdev);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+ platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, SMC_IO_EXTENT);

free_netdev(ndev);
@@ -2195,9 +2263,7 @@

if (ndev && level == RESUME_ENABLE) {
struct smc_local *lp = netdev_priv(ndev);
-
- if (pdev->num_resources == 3)
- smc_enable_device(pdev->resource[2].start);
+ smc_enable_device(pdev);
if (netif_running(ndev)) {
smc_reset(ndev);
smc_enable(ndev);
Index: 2.6/drivers/net/smc91x.h
===================================================================
--- 2.6.orig/drivers/net/smc91x.h 2005-01-04 14:11:08.000000000 +0000
+++ 2.6/drivers/net/smc91x.h 2005-01-25 14:47:42.000000000 +0000
@@ -362,7 +362,7 @@
#define SMC_IO_SHIFT 0
#endif
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
-
+#define SMC_DATA_EXTENT (4)

/*
. Bank Select Register:
@@ -883,7 +883,7 @@
#endif

#if SMC_CAN_USE_32BIT
-#define SMC_PUSH_DATA(p, l) \
+#define _SMC_PUSH_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -898,7 +898,7 @@
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \
} while (0)
-#define SMC_PULL_DATA(p, l) \
+#define _SMC_PULL_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -918,11 +918,11 @@
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
} while (0)
#elif SMC_CAN_USE_16BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#elif SMC_CAN_USE_8BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
-#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
+#define _SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
+#define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#endif

#if ! SMC_CAN_USE_16BIT
@@ -941,6 +941,51 @@
})
#endif

+#if SMC_CAN_USE_DATACS
+#define SMC_PUSH_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if (__len >= 2 && (unsigned long)__ptr & 2) { \
+ __len -= 2; \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ __ptr += 2; \
+ } \
+ outsl(lp->datacs, __ptr, __len >> 2); \
+ if (__len & 2) { \
+ __ptr += (__len & ~3); \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ } \
+ } else { \
+ _SMC_PUSH_DATA(p, l); \
+ }
+
+#define SMC_PULL_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if ((unsigned long)__ptr & 2) { \
+ /* \
+ * We want 32bit alignment here. \
+ * Since some buses perform a full 32bit \
+ * fetch even for 16bit data we can't use \
+ * SMC_inw() here. Back both source (on chip \
+ * and destination) pointers of 2 bytes. \
+ */ \
+ __ptr -= 2; \
+ __len += 2; \
+ SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
+ } \
+ __len += 2; \
+ insl( lp->datacs, __ptr, __len >> 2); \
+ } else { \
+ _SMC_PULL_DATA(p, l); \
+ }
+#else
+#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
+#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
+#endif
+
#if !defined (SMC_INTERRUPT_PREAMBLE)
# define SMC_INTERRUPT_PREAMBLE
#endif
Index: 2.6/arch/arm/mach-sa1100/neponset.c
===================================================================
--- 2.6.orig/arch/arm/mach-sa1100/neponset.c 2005-01-04 14:10:53.000000000 +0000
+++ 2.6/arch/arm/mach-sa1100/neponset.c 2005-01-25 15:56:00.130447587 +0000
@@ -266,6 +266,7 @@

static struct resource smc91x_resources[] = {
[0] = {
+ .name = "smc91x-regs",
.start = SA1100_CS3_PHYS,
.end = SA1100_CS3_PHYS + 0x01ffffff,
.flags = IORESOURCE_MEM,
@@ -276,6 +277,7 @@
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = "smc91x-attrib",
.start = SA1100_CS3_PHYS + 0x02000000,
.end = SA1100_CS3_PHYS + 0x03ffffff,
.flags = IORESOURCE_MEM,
Index: 2.6/arch/arm/mach-pxa/lubbock.c
===================================================================
--- 2.6.orig/arch/arm/mach-pxa/lubbock.c 2005-01-04 14:10:53.000000000 +0000
+++ 2.6/arch/arm/mach-pxa/lubbock.c 2005-01-25 15:56:00.048469724 +0000
@@ -137,6 +137,7 @@

static struct resource smc91x_resources[] = {
[0] = {
+ .name = "smc91x-regs",
.start = 0x0c000000,
.end = 0x0c0fffff,
.flags = IORESOURCE_MEM,
@@ -147,6 +148,7 @@
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = "smc91x-attrib",
.start = 0x0e000000,
.end = 0x0e0fffff,
.flags = IORESOURCE_MEM,

--
Ian Campbell, Senior Design Engineer
Web: http://www.arcom.com
Arcom, Clifton Road, Direct: +44 (0)1223 403 465
Cambridge CB1 7EA, United Kingdom Phone: +44 (0)1223 411 200