Commit 29830406 authored by Stephane Grosjean's avatar Stephane Grosjean Committed by Marc Kleine-Budde

can: peak_pci: Fix the way channels are linked together

Change the way channels objects are linked together by peak_pci_probe()
avoiding any kernel oops when driver is removed. Side effect is that
the list is now browsed from last to first channel.
Signed-off-by: default avatarStephane Grosjean <s.grosjean@peak-system.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent d0a71a7e
...@@ -40,7 +40,7 @@ MODULE_LICENSE("GPL v2"); ...@@ -40,7 +40,7 @@ MODULE_LICENSE("GPL v2");
struct peak_pci_chan { struct peak_pci_chan {
void __iomem *cfg_base; /* Common for all channels */ void __iomem *cfg_base; /* Common for all channels */
struct net_device *next_dev; /* Chain of network devices */ struct net_device *prev_dev; /* Chain of network devices */
u16 icr_mask; /* Interrupt mask for fast ack */ u16 icr_mask; /* Interrupt mask for fast ack */
}; };
...@@ -98,7 +98,7 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev, ...@@ -98,7 +98,7 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
{ {
struct sja1000_priv *priv; struct sja1000_priv *priv;
struct peak_pci_chan *chan; struct peak_pci_chan *chan;
struct net_device *dev, *dev0 = NULL; struct net_device *dev;
void __iomem *cfg_base, *reg_base; void __iomem *cfg_base, *reg_base;
u16 sub_sys_id, icr; u16 sub_sys_id, icr;
int i, err, channels; int i, err, channels;
...@@ -196,18 +196,14 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev, ...@@ -196,18 +196,14 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
} }
/* Create chain of SJA1000 devices */ /* Create chain of SJA1000 devices */
if (i == 0) chan->prev_dev = pci_get_drvdata(pdev);
dev0 = dev; pci_set_drvdata(pdev, dev);
else
chan->next_dev = dev;
dev_info(&pdev->dev, dev_info(&pdev->dev,
"%s at reg_base=0x%p cfg_base=0x%p irq=%d\n", "%s at reg_base=0x%p cfg_base=0x%p irq=%d\n",
dev->name, priv->reg_base, chan->cfg_base, dev->irq); dev->name, priv->reg_base, chan->cfg_base, dev->irq);
} }
pci_set_drvdata(pdev, dev0);
/* Enable interrupts */ /* Enable interrupts */
writew(icr, cfg_base + PITA_ICR + 2); writew(icr, cfg_base + PITA_ICR + 2);
...@@ -217,12 +213,11 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev, ...@@ -217,12 +213,11 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
/* Disable interrupts */ /* Disable interrupts */
writew(0x0, cfg_base + PITA_ICR + 2); writew(0x0, cfg_base + PITA_ICR + 2);
for (dev = dev0; dev; dev = chan->next_dev) { for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) {
unregister_sja1000dev(dev); unregister_sja1000dev(dev);
free_sja1000dev(dev); free_sja1000dev(dev);
priv = netdev_priv(dev); priv = netdev_priv(dev);
chan = priv->priv; chan = priv->priv;
dev = chan->next_dev;
} }
pci_iounmap(pdev, reg_base); pci_iounmap(pdev, reg_base);
...@@ -241,7 +236,7 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev, ...@@ -241,7 +236,7 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
static void __devexit peak_pci_remove(struct pci_dev *pdev) static void __devexit peak_pci_remove(struct pci_dev *pdev)
{ {
struct net_device *dev = pci_get_drvdata(pdev); /* First device */ struct net_device *dev = pci_get_drvdata(pdev); /* Last device */
struct sja1000_priv *priv = netdev_priv(dev); struct sja1000_priv *priv = netdev_priv(dev);
struct peak_pci_chan *chan = priv->priv; struct peak_pci_chan *chan = priv->priv;
void __iomem *cfg_base = chan->cfg_base; void __iomem *cfg_base = chan->cfg_base;
...@@ -255,7 +250,7 @@ static void __devexit peak_pci_remove(struct pci_dev *pdev) ...@@ -255,7 +250,7 @@ static void __devexit peak_pci_remove(struct pci_dev *pdev)
dev_info(&pdev->dev, "removing device %s\n", dev->name); dev_info(&pdev->dev, "removing device %s\n", dev->name);
unregister_sja1000dev(dev); unregister_sja1000dev(dev);
free_sja1000dev(dev); free_sja1000dev(dev);
dev = chan->next_dev; dev = chan->prev_dev;
if (!dev) if (!dev)
break; break;
priv = netdev_priv(dev); priv = netdev_priv(dev);
......
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