X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fwan%2Fdscc4.c;h=520a77a798e25482ee52852fa97d17edfc7e2191;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=fffe120851e51b54a5a02a5fb5887b6cc0af019f;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index fffe12085..520a77a79 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -125,9 +125,9 @@ static u32 dscc4_pci_config_store[16]; MODULE_AUTHOR("Maintainer: Francois Romieu "); MODULE_DESCRIPTION("Siemens PEB20534 PCI Controler"); MODULE_LICENSE("GPL"); -MODULE_PARM(debug,"i"); +module_param(debug, int, 0); MODULE_PARM_DESC(debug,"Enable/disable extra messages"); -MODULE_PARM(quartz,"i"); +module_param(quartz, int, 0); MODULE_PARM_DESC(quartz,"If present, on-board quartz frequency (Hz)"); /* Structures */ @@ -230,6 +230,7 @@ struct dscc4_dev_priv { unsigned short parity; struct net_device *dev; sync_serial_settings settings; + void __iomem *base_addr; u32 __pad __attribute__ ((aligned (4))); }; @@ -353,7 +354,7 @@ struct dscc4_dev_priv { /* Functions prototypes */ static void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); static void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); -static int dscc4_found1(struct pci_dev *, unsigned long ioaddr); +static int dscc4_found1(struct pci_dev *, void __iomem *ioaddr); static int dscc4_init_one(struct pci_dev *, const struct pci_device_id *ent); static int dscc4_open(struct net_device *); static int dscc4_start_xmit(struct sk_buff *, struct net_device *); @@ -390,7 +391,7 @@ static void scc_patchl(u32 mask, u32 value, struct dscc4_dev_priv *dpriv, state &= ~mask; state |= value; dpriv->scc_regs[offset >> 2] = state; - writel(state, dev->base_addr + SCC_REG_START(dpriv) + offset); + writel(state, dpriv->base_addr + SCC_REG_START(dpriv) + offset); } static void scc_writel(u32 bits, struct dscc4_dev_priv *dpriv, @@ -401,7 +402,7 @@ static void scc_writel(u32 bits, struct dscc4_dev_priv *dpriv, * As of 2002/02/16, there are no thread racing for access. */ dpriv->scc_regs[offset >> 2] = bits; - writel(bits, dev->base_addr + SCC_REG_START(dpriv) + offset); + writel(bits, dpriv->base_addr + SCC_REG_START(dpriv) + offset); } static inline u32 scc_readl(struct dscc4_dev_priv *dpriv, int offset) @@ -412,8 +413,8 @@ static inline u32 scc_readl(struct dscc4_dev_priv *dpriv, int offset) static u32 scc_readl_star(struct dscc4_dev_priv *dpriv, struct net_device *dev) { /* Cf errata DS5 p.4 */ - readl(dev->base_addr + SCC_REG_START(dpriv) + STAR); - return readl(dev->base_addr + SCC_REG_START(dpriv) + STAR); + readl(dpriv->base_addr + SCC_REG_START(dpriv) + STAR); + return readl(dpriv->base_addr + SCC_REG_START(dpriv) + STAR); } static inline void dscc4_do_tx(struct dscc4_dev_priv *dpriv, @@ -421,9 +422,9 @@ static inline void dscc4_do_tx(struct dscc4_dev_priv *dpriv, { dpriv->ltda = dpriv->tx_fd_dma + ((dpriv->tx_current-1)%TX_RING_SIZE)*sizeof(struct TxFD); - writel(dpriv->ltda, dev->base_addr + CH0LTDA + dpriv->dev_id*4); + writel(dpriv->ltda, dpriv->base_addr + CH0LTDA + dpriv->dev_id*4); /* Flush posted writes *NOW* */ - readl(dev->base_addr + CH0LTDA + dpriv->dev_id*4); + readl(dpriv->base_addr + CH0LTDA + dpriv->dev_id*4); } static inline void dscc4_rx_update(struct dscc4_dev_priv *dpriv, @@ -431,7 +432,7 @@ static inline void dscc4_rx_update(struct dscc4_dev_priv *dpriv, { dpriv->lrda = dpriv->rx_fd_dma + ((dpriv->rx_dirty - 1)%RX_RING_SIZE)*sizeof(struct RxFD); - writel(dpriv->lrda, dev->base_addr + CH0LRDA + dpriv->dev_id*4); + writel(dpriv->lrda, dpriv->base_addr + CH0LRDA + dpriv->dev_id*4); } static inline unsigned int dscc4_tx_done(struct dscc4_dev_priv *dpriv) @@ -442,7 +443,7 @@ static inline unsigned int dscc4_tx_done(struct dscc4_dev_priv *dpriv) static inline unsigned int dscc4_tx_quiescent(struct dscc4_dev_priv *dpriv, struct net_device *dev) { - return readl(dev->base_addr + CH0FTDA + dpriv->dev_id*4) == dpriv->ltda; + return readl(dpriv->base_addr + CH0FTDA + dpriv->dev_id*4) == dpriv->ltda; } int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev, @@ -517,9 +518,7 @@ inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev) skb = dev_alloc_skb(len); dpriv->rx_skbuff[dirty] = skb; if (skb) { - skb->dev = dev; skb->protocol = hdlc_type_trans(skb, dev); - skb->mac.raw = skb->data; rx_fd->data = pci_map_single(dpriv->pci_priv->pdev, skb->data, len, PCI_DMA_FROMDEVICE); } else { @@ -554,7 +553,7 @@ done: static int dscc4_do_action(struct net_device *dev, char *msg) { - unsigned long ioaddr = dev->base_addr; + void __iomem *ioaddr = dscc4_priv(dev)->base_addr; s16 i = 0; writel(Action, ioaddr + GCMDR); @@ -603,11 +602,11 @@ static void dscc4_rx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev) spin_lock_irqsave(&dpriv->pci_priv->lock, flags); /* Cf errata DS5 p.6 */ - writel(0x00000000, dev->base_addr + CH0LRDA + dpriv->dev_id*4); + writel(0x00000000, dpriv->base_addr + CH0LRDA + dpriv->dev_id*4); scc_patchl(PowerUp, 0, dpriv, dev, CCR0); - readl(dev->base_addr + CH0LRDA + dpriv->dev_id*4); - writel(MTFi|Rdr, dev->base_addr + dpriv->dev_id*0x0c + CH0CFG); - writel(Action, dev->base_addr + GCMDR); + readl(dpriv->base_addr + CH0LRDA + dpriv->dev_id*4); + writel(MTFi|Rdr, dpriv->base_addr + dpriv->dev_id*0x0c + CH0CFG); + writel(Action, dpriv->base_addr + GCMDR); spin_unlock_irqrestore(&dpriv->pci_priv->lock, flags); } @@ -629,7 +628,7 @@ static void dscc4_tx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev) wmb(); } - writel(MTFi|Rdt, dev->base_addr + dpriv->dev_id*0x0c + CH0CFG); + writel(MTFi|Rdt, dpriv->base_addr + dpriv->dev_id*0x0c + CH0CFG); if (dscc4_do_action(dev, "Rdt") < 0) printk(KERN_ERR "%s: Tx reset failed\n", dev->name); } @@ -692,7 +691,7 @@ static void dscc4_free1(struct pci_dev *pdev) root = ppriv->root; for (i = 0; i < dev_per_card; i++) - unregister_hdlc_device(dscc4_to_dev(&root[i])); + unregister_hdlc_device(dscc4_to_dev(root + i)); pci_set_drvdata(pdev, NULL); @@ -707,33 +706,36 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, { struct dscc4_pci_priv *priv; struct dscc4_dev_priv *dpriv; - static int cards_found = 0; - unsigned long ioaddr; - int i; + void __iomem *ioaddr; + int i, rc; printk(KERN_DEBUG "%s", version); - if (pci_enable_device(pdev)) - goto err_out; - if (!request_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0), "registers")) { + rc = pci_enable_device(pdev); + if (rc < 0) + goto out; + + rc = pci_request_region(pdev, 0, "registers"); + if (rc < 0) { printk(KERN_ERR "%s: can't reserve MMIO region (regs)\n", DRV_NAME); - goto err_out; + goto err_disable_0; } - if (!request_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1), "LBI interface")) { + rc = pci_request_region(pdev, 1, "LBI interface"); + if (rc < 0) { printk(KERN_ERR "%s: can't reserve MMIO region (lbi)\n", DRV_NAME); - goto err_out_free_mmio_region0; + goto err_free_mmio_region_1; } - ioaddr = (unsigned long)ioremap(pci_resource_start(pdev, 0), + + ioaddr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!ioaddr) { printk(KERN_ERR "%s: cannot remap MMIO region %lx @ %lx\n", DRV_NAME, pci_resource_len(pdev, 0), pci_resource_start(pdev, 0)); - goto err_out_free_mmio_region; + rc = -EIO; + goto err_free_mmio_regions_2; } printk(KERN_DEBUG "Siemens DSCC4, MMIO at %#lx (regs), %#lx (lbi), IRQ %d\n", pci_resource_start(pdev, 0), @@ -743,14 +745,16 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xf8); pci_set_master(pdev); - if (dscc4_found1(pdev, ioaddr)) - goto err_out_iounmap; + rc = dscc4_found1(pdev, ioaddr); + if (rc < 0) + goto err_iounmap_3; - priv = (struct dscc4_pci_priv *)pci_get_drvdata(pdev); + priv = pci_get_drvdata(pdev); - if (request_irq(pdev->irq, &dscc4_irq, SA_SHIRQ, DRV_NAME, priv->root)){ + rc = request_irq(pdev->irq, dscc4_irq, SA_SHIRQ, DRV_NAME, priv->root); + if (rc < 0) { printk(KERN_WARNING "%s: IRQ %d busy\n", DRV_NAME, pdev->irq); - goto err_out_free1; + goto err_release_4; } /* power up/little endian/dma core controlled via lrda/ltda */ @@ -770,9 +774,11 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, priv->iqcfg = (u32 *) pci_alloc_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), &priv->iqcfg_dma); if (!priv->iqcfg) - goto err_out_free_irq; + goto err_free_irq_5; writel(priv->iqcfg_dma, ioaddr + IQCFG); + rc = -ENOMEM; + /* * SCC 0-3 private rx/tx irq structures * IQRX/TXi needs to be set soon. Learned it the hard way... @@ -782,7 +788,7 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, dpriv->iqtx = (u32 *) pci_alloc_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), &dpriv->iqtx_dma); if (!dpriv->iqtx) - goto err_out_free_iqtx; + goto err_free_iqtx_6; writel(dpriv->iqtx_dma, ioaddr + IQTX0 + i*4); } for (i = 0; i < dev_per_card; i++) { @@ -790,7 +796,7 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, dpriv->iqrx = (u32 *) pci_alloc_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), &dpriv->iqrx_dma); if (!dpriv->iqrx) - goto err_out_free_iqrx; + goto err_free_iqrx_7; writel(dpriv->iqrx_dma, ioaddr + IQRX0 + i*4); } @@ -805,17 +811,18 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, writel(0xff200001, ioaddr + GCMDR); - cards_found++; - return 0; + rc = 0; +out: + return rc; -err_out_free_iqrx: +err_free_iqrx_7: while (--i >= 0) { dpriv = priv->root + i; pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), dpriv->iqrx, dpriv->iqrx_dma); } i = dev_per_card; -err_out_free_iqtx: +err_free_iqtx_6: while (--i >= 0) { dpriv = priv->root + i; pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), @@ -823,20 +830,19 @@ err_out_free_iqtx: } pci_free_consistent(pdev, IRQ_RING_SIZE*sizeof(u32), priv->iqcfg, priv->iqcfg_dma); -err_out_free_irq: +err_free_irq_5: free_irq(pdev->irq, priv->root); -err_out_free1: +err_release_4: dscc4_free1(pdev); -err_out_iounmap: - iounmap ((void *)ioaddr); -err_out_free_mmio_region: - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); -err_out_free_mmio_region0: - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); -err_out: - return -ENODEV; +err_iounmap_3: + iounmap (ioaddr); +err_free_mmio_regions_2: + pci_release_region(pdev, 1); +err_free_mmio_region_1: + pci_release_region(pdev, 0); +err_disable_0: + pci_disable_device(pdev); + goto out; }; /* @@ -877,14 +883,13 @@ static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz) return ret; } -static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) +static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) { struct dscc4_pci_priv *ppriv; struct dscc4_dev_priv *root; int i, ret = -ENOMEM; - root = (struct dscc4_dev_priv *) - kmalloc(dev_per_card*sizeof(*root), GFP_KERNEL); + root = kmalloc(dev_per_card*sizeof(*root), GFP_KERNEL); if (!root) { printk(KERN_ERR "%s: can't allocate data\n", DRV_NAME); goto err_out; @@ -893,22 +898,17 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) for (i = 0; i < dev_per_card; i++) { root[i].dev = alloc_hdlcdev(root + i); - if (!root[i].dev) { - while (i--) - free_netdev(root[i].dev); + if (!root[i].dev) goto err_free_dev; - } } - ppriv = (struct dscc4_pci_priv *) kmalloc(sizeof(*ppriv), GFP_KERNEL); + ppriv = kmalloc(sizeof(*ppriv), GFP_KERNEL); if (!ppriv) { printk(KERN_ERR "%s: can't allocate private data\n", DRV_NAME); - goto err_free_dev2; + goto err_free_dev; } memset(ppriv, 0, sizeof(struct dscc4_pci_priv)); - ret = dscc4_set_quartz(root, quartz); - if (ret < 0) - goto err_free_priv; + ppriv->root = root; spin_lock_init(&ppriv->lock); @@ -917,7 +917,7 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) struct net_device *d = dscc4_to_dev(dpriv); hdlc_device *hdlc = dev_to_hdlc(d); - d->base_addr = ioaddr; + d->base_addr = (unsigned long)ioaddr; d->init = NULL; d->irq = pdev->irq; d->open = dscc4_open; @@ -931,6 +931,7 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) dpriv->dev_id = i; dpriv->pci_priv = ppriv; + dpriv->base_addr = ioaddr; spin_lock_init(&dpriv->lock); hdlc->xmit = dscc4_start_xmit; @@ -951,20 +952,24 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) goto err_unregister; } } + + ret = dscc4_set_quartz(root, quartz); + if (ret < 0) + goto err_unregister; + pci_set_drvdata(pdev, ppriv); return ret; err_unregister: - while (--i >= 0) { + while (i-- > 0) { dscc4_release_ring(root + i); - unregister_hdlc_device(dscc4_to_dev(&root[i])); + unregister_hdlc_device(dscc4_to_dev(root + i)); } -err_free_priv: kfree(ppriv); -err_free_dev2: - for (i = 0; i < dev_per_card; i++) - free_netdev(root[i].dev); + i = dev_per_card; err_free_dev: + while (i-- > 0) + free_netdev(root[i].dev); kfree(root); err_out: return ret; @@ -1009,7 +1014,7 @@ static int dscc4_loopback_check(struct dscc4_dev_priv *dpriv) * * This code doesn't need to be efficient. Keep It Simple */ -static void dscc4_pci_reset(struct pci_dev *pdev, unsigned long ioaddr) +static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr) { int i; @@ -1476,7 +1481,7 @@ static irqreturn_t dscc4_irq(int irq, void *token, struct pt_regs *ptregs) struct dscc4_dev_priv *root = token; struct dscc4_pci_priv *priv; struct net_device *dev; - unsigned long ioaddr; + void __iomem *ioaddr; u32 state; unsigned long flags; int i, handled = 1; @@ -1486,7 +1491,7 @@ static irqreturn_t dscc4_irq(int irq, void *token, struct pt_regs *ptregs) spin_lock_irqsave(&priv->lock, flags); - ioaddr = dev->base_addr; + ioaddr = root->base_addr; state = readl(ioaddr + GSTAR); if (!state) { @@ -1613,8 +1618,8 @@ try: dpriv->flags = NeedIDT; /* Tx reset */ writel(MTFi | Rdt, - dev->base_addr + 0x0c*dpriv->dev_id + CH0CFG); - writel(Action, dev->base_addr + GCMDR); + dpriv->base_addr + 0x0c*dpriv->dev_id + CH0CFG); + writel(Action, dpriv->base_addr + GCMDR); return; } if (state & Cts) { @@ -1629,7 +1634,8 @@ try: goto try; } if (state & Xpr) { - unsigned long scc_addr, ring; + void __iomem *scc_addr; + unsigned long ring; int i; /* @@ -1643,7 +1649,7 @@ try: if (!i) printk(KERN_INFO "%s busy in irq\n", dev->name); - scc_addr = dev->base_addr + 0x0c*dpriv->dev_id; + scc_addr = dpriv->base_addr + 0x0c*dpriv->dev_id; /* Keep this order: IDT before IDR */ if (dpriv->flags & NeedIDT) { if (debug > 2) @@ -1801,12 +1807,12 @@ try: */ if (state & Rdo) { struct RxFD *rx_fd; - u32 scc_addr; + void __iomem *scc_addr; int cur; //if (debug) // dscc4_rx_dump(dpriv); - scc_addr = dev->base_addr + 0x0c*dpriv->dev_id; + scc_addr = dpriv->base_addr + 0x0c*dpriv->dev_id; scc_patchl(RxActivate, 0, dpriv, dev, CCR2); /* @@ -1970,13 +1976,13 @@ static void __devexit dscc4_remove_one(struct pci_dev *pdev) { struct dscc4_pci_priv *ppriv; struct dscc4_dev_priv *root; - unsigned long ioaddr; + void __iomem *ioaddr; int i; ppriv = pci_get_drvdata(pdev); root = ppriv->root; - ioaddr = dscc4_to_dev(root)->base_addr; + ioaddr = root->base_addr; dscc4_pci_reset(pdev, ioaddr); @@ -1995,12 +2001,12 @@ static void __devexit dscc4_remove_one(struct pci_dev *pdev) dscc4_free1(pdev); - iounmap((void *)ioaddr); + iounmap(ioaddr); + + pci_release_region(pdev, 1); + pci_release_region(pdev, 0); - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + pci_disable_device(pdev); } static int dscc4_hdlc_attach(struct net_device *dev, unsigned short encoding,