X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=drivers%2Fnet%2Fsmc91x.c;h=7ec08127c9d6c4f8594d805392155e3bddccd875;hb=0a3a98f6dd4e8f4d928a09302c0d1c56f2192ac3;hp=0ddaa611cc61657d424a3cc42313aac2b6916406;hpb=9dfb7808fb05643b0d06df7411b94d9546696bf1;p=sfrench%2Fcifs-2.6.git diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 0ddaa611cc61..7ec08127c9d6 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -77,7 +77,7 @@ static const char version[] = #include #include #include -#include +#include #include #include #include @@ -88,7 +88,6 @@ static const char version[] = #include #include -#include #include "smc91x.h" @@ -154,6 +153,12 @@ MODULE_LICENSE("GPL"); */ #define MEMORY_WAIT_TIME 16 +/* + * The maximum number of processing loops allowed for each call to the + * IRQ handler. + */ +#define MAX_IRQ_LOOPS 8 + /* * This selects whether TX packets are sent one by one to the SMC91x internal * memory and throttled until transmission completes. This may prevent @@ -684,7 +689,6 @@ static void smc_hardware_send_pkt(unsigned long data) /* queue the packet for TX */ SMC_SET_MMU_CMD(MC_ENQUEUE); - SMC_ACK_INT(IM_TX_EMPTY_INT); smc_special_unlock(&lp->lock); dev->trans_start = jiffies; @@ -1207,6 +1211,7 @@ static void smc_phy_configure(void *data) smc_phy_check_media(dev, 1); smc_phy_configure_exit: + SMC_SELECT_BANK(2); spin_unlock_irq(&lp->lock); lp->work_pending = 0; } @@ -1305,7 +1310,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) SMC_SET_INT_MASK(0); /* set a timeout value, so I don't stay here forever */ - timeout = 8; + timeout = MAX_IRQ_LOOPS; do { status = SMC_GET_INT(); @@ -1372,10 +1377,13 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* restore register states */ SMC_SET_PTR(saved_pointer); SMC_SET_INT_MASK(mask); - spin_unlock(&lp->lock); - DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); + if (timeout == MAX_IRQ_LOOPS) + PRINTK("%s: spurious interrupt (mask = 0x%02x)\n", + dev->name, mask); + DBG(3, "%s: Interrupt done (%d loops)\n", + dev->name, MAX_IRQ_LOOPS - timeout); /* * We return IRQ_HANDLED unconditionally here even if there was @@ -1983,6 +1991,10 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr) if (lp->version >= (CHIP_91100 << 4)) smc_phy_detect(dev); + /* then shut everything down to save power */ + smc_shutdown(dev); + smc_phy_powerdown(dev); + /* Set default parameters */ lp->msg_enable = NETIF_MSG_LINK; lp->ctl_rfduplx = 0; @@ -1994,12 +2006,10 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr) } /* Grab the IRQ */ - retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, &smc_interrupt, SMC_IRQ_FLAGS, dev->name, dev); if (retval) goto err_out; - set_irq_type(dev->irq, SMC_IRQ_TRIGGER_TYPE); - #ifdef SMC_USE_PXA_DMA { int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW, @@ -2179,9 +2189,8 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device * * 0 --> there is a device * anything else, error */ -static int smc_drv_probe(struct device *dev) +static int smc_drv_probe(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); struct net_device *ndev; struct resource *res; unsigned int __iomem *addr; @@ -2208,7 +2217,7 @@ static int smc_drv_probe(struct device *dev) goto out_release_io; } SET_MODULE_OWNER(ndev); - SET_NETDEV_DEV(ndev, dev); + SET_NETDEV_DEV(ndev, &pdev->dev); ndev->dma = (unsigned char)-1; ndev->irq = platform_get_irq(pdev, 0); @@ -2229,7 +2238,7 @@ static int smc_drv_probe(struct device *dev) goto out_release_attrib; } - dev_set_drvdata(dev, ndev); + platform_set_drvdata(pdev, ndev); ret = smc_probe(ndev, addr); if (ret != 0) goto out_iounmap; @@ -2245,7 +2254,7 @@ static int smc_drv_probe(struct device *dev) return 0; out_iounmap: - dev_set_drvdata(dev, NULL); + platform_set_drvdata(pdev, NULL); iounmap(addr); out_release_attrib: smc_release_attrib(pdev); @@ -2259,14 +2268,13 @@ static int smc_drv_probe(struct device *dev) return ret; } -static int smc_drv_remove(struct device *dev) +static int smc_drv_remove(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); - struct net_device *ndev = dev_get_drvdata(dev); + struct net_device *ndev = platform_get_drvdata(pdev); struct smc_local *lp = netdev_priv(ndev); struct resource *res; - dev_set_drvdata(dev, NULL); + platform_set_drvdata(pdev, NULL); unregister_netdev(ndev); @@ -2291,9 +2299,9 @@ static int smc_drv_remove(struct device *dev) return 0; } -static int smc_drv_suspend(struct device *dev, pm_message_t state) +static int smc_drv_suspend(struct platform_device *dev, pm_message_t state) { - struct net_device *ndev = dev_get_drvdata(dev); + struct net_device *ndev = platform_get_drvdata(dev); if (ndev) { if (netif_running(ndev)) { @@ -2305,14 +2313,13 @@ static int smc_drv_suspend(struct device *dev, pm_message_t state) return 0; } -static int smc_drv_resume(struct device *dev) +static int smc_drv_resume(struct platform_device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct net_device *ndev = dev_get_drvdata(dev); + struct net_device *ndev = platform_get_drvdata(dev); if (ndev) { struct smc_local *lp = netdev_priv(ndev); - smc_enable_device(pdev); + smc_enable_device(dev); if (netif_running(ndev)) { smc_reset(ndev); smc_enable(ndev); @@ -2324,13 +2331,14 @@ static int smc_drv_resume(struct device *dev) return 0; } -static struct device_driver smc_driver = { - .name = CARDNAME, - .bus = &platform_bus_type, +static struct platform_driver smc_driver = { .probe = smc_drv_probe, .remove = smc_drv_remove, .suspend = smc_drv_suspend, .resume = smc_drv_resume, + .driver = { + .name = CARDNAME, + }, }; static int __init smc_init(void) @@ -2344,12 +2352,12 @@ static int __init smc_init(void) #endif #endif - return driver_register(&smc_driver); + return platform_driver_register(&smc_driver); } static void __exit smc_cleanup(void) { - driver_unregister(&smc_driver); + platform_driver_unregister(&smc_driver); } module_init(smc_init);