#include <linux/delay.h>
#include <net/syncppp.h>
#include <linux/hdlc.h>
+#include <linux/mutex.h>
/* Version */
static const char version[] = "$Id: dscc4.c,v 1.173 2003/09/20 23:55:34 romieu Exp $ for Linux\n";
static int quartz;
#ifdef CONFIG_DSCC4_PCI_RST
-static DECLARE_MUTEX(dscc4_sem);
+static DEFINE_MUTEX(dscc4_mutex);
static u32 dscc4_pci_config_store[16];
#endif
MODULE_AUTHOR("Maintainer: Francois Romieu <romieu@cogenit.fr>");
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 */
static void dscc4_release_ring(struct dscc4_dev_priv *);
static void dscc4_timer(unsigned long);
static void dscc4_tx_timeout(struct net_device *);
-static irqreturn_t dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs);
+static irqreturn_t dscc4_irq(int irq, void *dev_id);
static int dscc4_hdlc_attach(struct net_device *, unsigned short, unsigned short);
static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *);
#ifdef DSCC4_POLLING
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,
- const char *msg)
+static int state_check(u32 state, struct dscc4_dev_priv *dpriv,
+ struct net_device *dev, const char *msg)
{
int ret = 0;
return ret;
}
-void dscc4_tx_print(struct net_device *dev, struct dscc4_dev_priv *dpriv,
- char *msg)
+static void dscc4_tx_print(struct net_device *dev,
+ struct dscc4_dev_priv *dpriv,
+ char *msg)
{
printk(KERN_DEBUG "%s: tx_current=%02d tx_dirty=%02d (%s)\n",
dev->name, dpriv->tx_current, dpriv->tx_dirty, msg);
}
}
-inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev)
+static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv,
+ struct net_device *dev)
{
unsigned int dirty = dpriv->rx_dirty%RX_RING_SIZE;
struct RxFD *rx_fd = dpriv->rx_fd + dirty;
msg, i);
goto done;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
rmb();
} while (++i > 0);
printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
(dpriv->iqtx[cur] & Xpr))
break;
smp_rmb();
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
} while (++i > 0);
return (i >= 0 ) ? i : -EAGAIN;
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);
{
struct dscc4_pci_priv *priv;
struct dscc4_dev_priv *dpriv;
- static int cards_found = 0;
void __iomem *ioaddr;
- int i;
+ 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 = 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;
+ printk(KERN_ERR "%s: cannot remap MMIO region %llx @ %llx\n",
+ DRV_NAME, (unsigned long long)pci_resource_len(pdev, 0),
+ (unsigned long long)pci_resource_start(pdev, 0));
+ 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),
- pci_resource_start(pdev, 1), pdev->irq);
+ printk(KERN_DEBUG "Siemens DSCC4, MMIO at %#llx (regs), %#llx (lbi), IRQ %d\n",
+ (unsigned long long)pci_resource_start(pdev, 0),
+ (unsigned long long)pci_resource_start(pdev, 1), pdev->irq);
/* Cf errata DS5 p.2 */
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, IRQF_SHARED, 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 */
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...
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++) {
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);
}
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),
}
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:
+err_iounmap_3:
iounmap (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_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;
};
/*
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;
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);
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;
{
int i;
- down(&dscc4_sem);
+ mutex_lock(&dscc4_mutex);
for (i = 0; i < 16; i++)
pci_read_config_dword(pdev, i << 2, dscc4_pci_config_store + i);
/* Flush posted writes */
readl(ioaddr + GSTAR);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_uninterruptible(10);
for (i = 0; i < 16; i++)
pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
- up(&dscc4_sem);
+ mutex_unlock(&dscc4_mutex);
}
#else
#define dscc4_pci_reset(pdev,ioaddr) do {} while (0)
return ret;
}
-static irqreturn_t dscc4_irq(int irq, void *token, struct pt_regs *ptregs)
+static irqreturn_t dscc4_irq(int irq, void *token)
{
struct dscc4_dev_priv *root = token;
struct dscc4_pci_priv *priv;
* It failed and locked solid. Thus the introduction of a dummy skb.
* Problem is acknowledged in errata sheet DS5. Joy :o/
*/
-struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
+static struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
{
struct sk_buff *skb;
(++i%TX_RING_SIZE)*sizeof(*tx_fd));
} while (i < TX_RING_SIZE);
- if (dscc4_init_dummy_skb(dpriv) < 0)
+ if (!dscc4_init_dummy_skb(dpriv))
goto err_free_dma_tx;
memset(dpriv->rx_skbuff, 0, sizeof(struct sk_buff *)*RX_RING_SIZE);
iounmap(ioaddr);
- 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_release_region(pdev, 1);
+ pci_release_region(pdev, 0);
+
+ pci_disable_device(pdev);
}
static int dscc4_hdlc_attach(struct net_device *dev, unsigned short encoding,
static int __init dscc4_init_module(void)
{
- return pci_module_init(&dscc4_driver);
+ return pci_register_driver(&dscc4_driver);
}
static void __exit dscc4_cleanup_module(void)