Commit b9dc97bb authored by Jeff Garzik's avatar Jeff Garzik

Merge pobox.com:/garz/repo/linux-2.6

into pobox.com:/garz/repo/netdev-2.6/smc91x
parents 0202b160 52433c9b
...@@ -138,6 +138,7 @@ static struct platform_device sa1111_device = { ...@@ -138,6 +138,7 @@ static struct platform_device sa1111_device = {
static struct resource smc91x_resources[] = { static struct resource smc91x_resources[] = {
[0] = { [0] = {
.name = "smc91x-regs",
.start = 0x0c000000, .start = 0x0c000000,
.end = 0x0c0fffff, .end = 0x0c0fffff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
...@@ -148,6 +149,7 @@ static struct resource smc91x_resources[] = { ...@@ -148,6 +149,7 @@ static struct resource smc91x_resources[] = {
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
[2] = { [2] = {
.name = "smc91x-attrib",
.start = 0x0e000000, .start = 0x0e000000,
.end = 0x0e0fffff, .end = 0x0e0fffff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
......
...@@ -266,6 +266,7 @@ static struct platform_device sa1111_device = { ...@@ -266,6 +266,7 @@ static struct platform_device sa1111_device = {
static struct resource smc91x_resources[] = { static struct resource smc91x_resources[] = {
[0] = { [0] = {
.name = "smc91x-regs",
.start = SA1100_CS3_PHYS, .start = SA1100_CS3_PHYS,
.end = SA1100_CS3_PHYS + 0x01ffffff, .end = SA1100_CS3_PHYS + 0x01ffffff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
...@@ -276,6 +277,7 @@ static struct resource smc91x_resources[] = { ...@@ -276,6 +277,7 @@ static struct resource smc91x_resources[] = {
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
[2] = { [2] = {
.name = "smc91x-attrib",
.start = SA1100_CS3_PHYS + 0x02000000, .start = SA1100_CS3_PHYS + 0x02000000,
.end = SA1100_CS3_PHYS + 0x03ffffff, .end = SA1100_CS3_PHYS + 0x03ffffff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
......
...@@ -210,6 +210,10 @@ struct smc_local { ...@@ -210,6 +210,10 @@ struct smc_local {
spinlock_t lock; spinlock_t lock;
#ifdef SMC_CAN_USE_DATACS
u32 *datacs;
#endif
#ifdef SMC_USE_PXA_DMA #ifdef SMC_USE_PXA_DMA
/* DMA needs the physical address of the chip */ /* DMA needs the physical address of the chip */
u_long physaddr; u_long physaddr;
...@@ -483,7 +487,19 @@ static inline void smc_rcv(struct net_device *dev) ...@@ -483,7 +487,19 @@ static inline void smc_rcv(struct net_device *dev)
dev->name, packet_number, status, dev->name, packet_number, status,
packet_len, packet_len); packet_len, packet_len);
if (unlikely(status & RS_ERRORS)) { back:
if (unlikely(packet_len < 6 || status & RS_ERRORS)) {
if (status & RS_TOOLONG && packet_len <= (1514 + 4 + 6)) {
/* accept VLAN packets */
status &= ~RS_TOOLONG;
goto back;
}
if (packet_len < 6) {
/* bloody hardware */
printk(KERN_ERR "%s: fubar (rxlen %u status %x\n",
dev->name, packet_len, status);
status |= RS_TOOSHORT;
}
SMC_WAIT_MMU_BUSY(); SMC_WAIT_MMU_BUSY();
SMC_SET_MMU_CMD(MC_RELEASE); SMC_SET_MMU_CMD(MC_RELEASE);
lp->stats.rx_errors++; lp->stats.rx_errors++;
...@@ -508,7 +524,7 @@ static inline void smc_rcv(struct net_device *dev) ...@@ -508,7 +524,7 @@ static inline void smc_rcv(struct net_device *dev)
* (2 bytes, possibly containing the payload odd byte). * (2 bytes, possibly containing the payload odd byte).
* Furthermore, we add 2 bytes to allow rounding up to * Furthermore, we add 2 bytes to allow rounding up to
* multiple of 4 bytes on 32 bit buses. * multiple of 4 bytes on 32 bit buses.
* Ence packet_len - 6 + 2 + 2 + 2. * Hence packet_len - 6 + 2 + 2 + 2.
*/ */
skb = dev_alloc_skb(packet_len); skb = dev_alloc_skb(packet_len);
if (unlikely(skb == NULL)) { if (unlikely(skb == NULL)) {
...@@ -2012,16 +2028,21 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) ...@@ -2012,16 +2028,21 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
return retval; return retval;
} }
static int smc_enable_device(unsigned long attrib_phys) static int smc_enable_device(struct platform_device *pdev)
{ {
unsigned long flags; unsigned long flags;
unsigned char ecor, ecsr; unsigned char ecor, ecsr;
void *addr; 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. * Map the attribute space. This is overkill, but clean.
*/ */
addr = ioremap(attrib_phys, ATTRIB_SIZE); addr = ioremap(res->start, ATTRIB_SIZE);
if (!addr) if (!addr)
return -ENOMEM; return -ENOMEM;
...@@ -2069,6 +2090,62 @@ static int smc_enable_device(unsigned long attrib_phys) ...@@ -2069,6 +2090,62 @@ static int smc_enable_device(unsigned long attrib_phys)
return 0; 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) * smc_init(void)
* Input parameters: * Input parameters:
...@@ -2084,20 +2161,20 @@ static int smc_drv_probe(struct device *dev) ...@@ -2084,20 +2161,20 @@ static int smc_drv_probe(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev; struct net_device *ndev;
struct resource *res, *ext = NULL; struct resource *res;
unsigned int *addr; unsigned int *addr;
int ret; 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) { if (!res) {
ret = -ENODEV; ret = -ENODEV;
goto out; goto out;
} }
/*
* Request the regions. if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
*/
if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
...@@ -2106,7 +2183,7 @@ static int smc_drv_probe(struct device *dev) ...@@ -2106,7 +2183,7 @@ static int smc_drv_probe(struct device *dev)
if (!ndev) { if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME); printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM; ret = -ENOMEM;
goto release_1; goto out_release_io;
} }
SET_MODULE_OWNER(ndev); SET_MODULE_OWNER(ndev);
SET_NETDEV_DEV(ndev, dev); SET_NETDEV_DEV(ndev, dev);
...@@ -2114,42 +2191,26 @@ static int smc_drv_probe(struct device *dev) ...@@ -2114,42 +2191,26 @@ static int smc_drv_probe(struct device *dev)
ndev->dma = (unsigned char)-1; ndev->dma = (unsigned char)-1;
ndev->irq = platform_get_irq(pdev, 0); ndev->irq = platform_get_irq(pdev, 0);
ext = platform_get_resource(pdev, IORESOURCE_MEM, 1); ret = smc_request_attrib(pdev);
if (ext) { if (ret)
if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) { goto out_free_netdev;
ret = -EBUSY;
goto release_1;
}
#if defined(CONFIG_SA1100_ASSABET) #if defined(CONFIG_SA1100_ASSABET)
NCR_0 |= NCR_ENET_OSC_EN; NCR_0 |= NCR_ENET_OSC_EN;
#endif #endif
ret = smc_enable_device(pdev);
ret = smc_enable_device(ext->start); if (ret)
if (ret) goto out_release_attrib;
goto release_both;
}
addr = ioremap(res->start, SMC_IO_EXTENT); addr = ioremap(res->start, SMC_IO_EXTENT);
if (!addr) { if (!addr) {
ret = -ENOMEM; ret = -ENOMEM;
goto release_both; goto out_release_attrib;
} }
dev_set_drvdata(dev, ndev); dev_set_drvdata(dev, ndev);
ret = smc_probe(ndev, (unsigned long)addr); ret = smc_probe(ndev, (unsigned long)addr);
if (ret != 0) { if (ret != 0)
dev_set_drvdata(dev, NULL); goto out_iounmap;
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);
}
#ifdef SMC_USE_PXA_DMA #ifdef SMC_USE_PXA_DMA
else { else {
struct smc_local *lp = netdev_priv(ndev); struct smc_local *lp = netdev_priv(ndev);
...@@ -2157,6 +2218,22 @@ static int smc_drv_probe(struct device *dev) ...@@ -2157,6 +2218,22 @@ static int smc_drv_probe(struct device *dev)
} }
#endif #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; return ret;
} }
...@@ -2177,10 +2254,13 @@ static int smc_drv_remove(struct device *dev) ...@@ -2177,10 +2254,13 @@ static int smc_drv_remove(struct device *dev)
pxa_free_dma(ndev->dma); pxa_free_dma(ndev->dma);
#endif #endif
iounmap((void *)ndev->base_addr); iounmap((void *)ndev->base_addr);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res) smc_release_datacs(pdev,ndev);
release_mem_region(res->start, ATTRIB_SIZE); smc_release_attrib(pdev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
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); release_mem_region(res->start, SMC_IO_EXTENT);
free_netdev(ndev); free_netdev(ndev);
...@@ -2208,9 +2288,7 @@ static int smc_drv_resume(struct device *dev, u32 level) ...@@ -2208,9 +2288,7 @@ static int smc_drv_resume(struct device *dev, u32 level)
if (ndev && level == RESUME_ENABLE) { if (ndev && level == RESUME_ENABLE) {
struct smc_local *lp = netdev_priv(ndev); struct smc_local *lp = netdev_priv(ndev);
smc_enable_device(pdev);
if (pdev->num_resources == 3)
smc_enable_device(pdev->resource[2].start);
if (netif_running(ndev)) { if (netif_running(ndev)) {
smc_reset(ndev); smc_reset(ndev);
smc_enable(ndev); smc_enable(ndev);
......
...@@ -362,7 +362,7 @@ smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs) ...@@ -362,7 +362,7 @@ smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
#define SMC_IO_SHIFT 0 #define SMC_IO_SHIFT 0
#endif #endif
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT) #define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
#define SMC_DATA_EXTENT (4)
/* /*
. Bank Select Register: . Bank Select Register:
...@@ -883,7 +883,7 @@ static const char * chip_ids[ 16 ] = { ...@@ -883,7 +883,7 @@ static const char * chip_ids[ 16 ] = {
#endif #endif
#if SMC_CAN_USE_32BIT #if SMC_CAN_USE_32BIT
#define SMC_PUSH_DATA(p, l) \ #define _SMC_PUSH_DATA(p, l) \
do { \ do { \
char *__ptr = (p); \ char *__ptr = (p); \
int __len = (l); \ int __len = (l); \
...@@ -898,7 +898,7 @@ static const char * chip_ids[ 16 ] = { ...@@ -898,7 +898,7 @@ static const char * chip_ids[ 16 ] = {
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \ } \
} while (0) } while (0)
#define SMC_PULL_DATA(p, l) \ #define _SMC_PULL_DATA(p, l) \
do { \ do { \
char *__ptr = (p); \ char *__ptr = (p); \
int __len = (l); \ int __len = (l); \
...@@ -918,11 +918,11 @@ static const char * chip_ids[ 16 ] = { ...@@ -918,11 +918,11 @@ static const char * chip_ids[ 16 ] = {
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \ SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
} while (0) } while (0)
#elif SMC_CAN_USE_16BIT #elif SMC_CAN_USE_16BIT
#define SMC_PUSH_DATA(p, l) SMC_outsw( 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 ) #define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#elif SMC_CAN_USE_8BIT #elif SMC_CAN_USE_8BIT
#define SMC_PUSH_DATA(p, l) SMC_outsb( 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 ) #define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#endif #endif
#if ! SMC_CAN_USE_16BIT #if ! SMC_CAN_USE_16BIT
...@@ -941,6 +941,51 @@ static const char * chip_ids[ 16 ] = { ...@@ -941,6 +941,51 @@ static const char * chip_ids[ 16 ] = {
}) })
#endif #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) #if !defined (SMC_INTERRUPT_PREAMBLE)
# define SMC_INTERRUPT_PREAMBLE # define SMC_INTERRUPT_PREAMBLE
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment