Skip to content

Commit c51da42

Browse files
mgrzeschikdavem330
authored andcommitted
ARCNET: add support for multi interfaces on com20020
The com20020-pci driver is currently designed to instance one netdev with one pci device. This patch adds support to instance many cards with one pci device, depending on the device data in the private data. Signed-off-by: Michael Grzeschik <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8c14f9c commit c51da42

File tree

3 files changed

+109
-59
lines changed

3 files changed

+109
-59
lines changed

drivers/net/arcnet/com20020-pci.c

Lines changed: 95 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <linux/pci.h>
3939
#include <linux/arcdevice.h>
4040
#include <linux/com20020.h>
41+
#include <linux/list.h>
4142

4243
#include <asm/io.h>
4344

@@ -61,85 +62,125 @@ module_param(clockp, int, 0);
6162
module_param(clockm, int, 0);
6263
MODULE_LICENSE("GPL");
6364

65+
static void com20020pci_remove(struct pci_dev *pdev);
66+
6467
static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
6568
{
66-
struct com20020_pci_channel_map *cm;
6769
struct com20020_pci_card_info *ci;
6870
struct net_device *dev;
6971
struct arcnet_local *lp;
70-
int ioaddr, err;
72+
struct com20020_priv *priv;
73+
int i, ioaddr, ret;
74+
struct resource *r;
7175

7276
if (pci_enable_device(pdev))
7377
return -EIO;
74-
dev = alloc_arcdev(device);
75-
if (!dev)
76-
return -ENOMEM;
77-
78-
dev->netdev_ops = &com20020_netdev_ops;
7978

79+
priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv),
80+
GFP_KERNEL);
8081
ci = (struct com20020_pci_card_info *)id->driver_data;
82+
priv->ci = ci;
8183

82-
lp = netdev_priv(dev);
84+
INIT_LIST_HEAD(&priv->list_dev);
8385

84-
pci_set_drvdata(pdev, dev);
8586

86-
cm = &ci->chan_map_tbl[0];
87-
BUGMSG(D_NORMAL, "%s Controls\n", ci->name);
88-
ioaddr = pci_resource_start(pdev, cm->bar);
87+
for (i = 0; i < ci->devcount; i++) {
88+
struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
89+
struct com20020_dev *card;
8990

90-
if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com20020-pci")) {
91-
BUGMSG(D_INIT, "IO region %xh-%xh already allocated.\n",
92-
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
93-
err = -EBUSY;
94-
goto out_dev;
95-
}
91+
dev = alloc_arcdev(device);
92+
if (!dev) {
93+
ret = -ENOMEM;
94+
goto out_port;
95+
}
9696

97-
// Dummy access after Reset
98-
// ARCNET controller needs this access to detect bustype
99-
outb(0x00,ioaddr+1);
100-
inb(ioaddr+1);
101-
102-
dev->base_addr = ioaddr;
103-
dev->irq = pdev->irq;
104-
dev->dev_addr[0] = node;
105-
lp->card_name = "PCI COM20020";
106-
lp->card_flags = ci->flags;
107-
lp->backplane = backplane;
108-
lp->clockp = clockp & 7;
109-
lp->clockm = clockm & 3;
110-
lp->timeout = timeout;
111-
lp->hw.owner = THIS_MODULE;
112-
113-
if (ASTATUS() == 0xFF) {
114-
BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, "
115-
"but seems empty!\n", ioaddr);
116-
err = -EIO;
117-
goto out_port;
118-
}
119-
if (com20020_check(dev)) {
120-
err = -EIO;
121-
goto out_port;
97+
dev->netdev_ops = &com20020_netdev_ops;
98+
99+
lp = netdev_priv(dev);
100+
101+
BUGMSG(D_NORMAL, "%s Controls\n", ci->name);
102+
ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
103+
104+
r = devm_request_region(&pdev->dev, ioaddr, cm->size,
105+
"com20020-pci");
106+
if (!r) {
107+
pr_err("IO region %xh-%xh already allocated.\n",
108+
ioaddr, ioaddr + cm->size - 1);
109+
ret = -EBUSY;
110+
goto out_port;
111+
}
112+
113+
/* Dummy access after Reset
114+
* ARCNET controller needs
115+
* this access to detect bustype
116+
*/
117+
outb(0x00, ioaddr + 1);
118+
inb(ioaddr + 1);
119+
120+
dev->base_addr = ioaddr;
121+
dev->dev_addr[0] = node;
122+
dev->irq = pdev->irq;
123+
lp->card_name = "PCI COM20020";
124+
lp->card_flags = ci->flags;
125+
lp->backplane = backplane;
126+
lp->clockp = clockp & 7;
127+
lp->clockm = clockm & 3;
128+
lp->timeout = timeout;
129+
lp->hw.owner = THIS_MODULE;
130+
131+
if (ASTATUS() == 0xFF) {
132+
pr_err("IO address %Xh is empty!\n", ioaddr);
133+
ret = -EIO;
134+
goto out_port;
135+
}
136+
if (com20020_check(dev)) {
137+
ret = -EIO;
138+
goto out_port;
139+
}
140+
141+
card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
142+
GFP_KERNEL);
143+
if (!card) {
144+
pr_err("%s out of memory!\n", __func__);
145+
return -ENOMEM;
146+
}
147+
148+
card->index = i;
149+
card->pci_priv = priv;
150+
card->dev = dev;
151+
152+
dev_set_drvdata(&dev->dev, card);
153+
154+
ret = com20020_found(dev, IRQF_SHARED);
155+
if (ret)
156+
goto out_port;
157+
158+
list_add(&card->list, &priv->list_dev);
122159
}
123160

124-
if ((err = com20020_found(dev, IRQF_SHARED)) != 0)
125-
goto out_port;
161+
pci_set_drvdata(pdev, priv);
126162

127163
return 0;
128164

129165
out_port:
130-
release_region(ioaddr, ARCNET_TOTAL_SIZE);
131-
out_dev:
132-
free_netdev(dev);
133-
return err;
166+
com20020pci_remove(pdev);
167+
return ret;
134168
}
135169

136170
static void com20020pci_remove(struct pci_dev *pdev)
137171
{
138-
struct net_device *dev = pci_get_drvdata(pdev);
139-
unregister_netdev(dev);
140-
free_irq(dev->irq, dev);
141-
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
142-
free_netdev(dev);
172+
struct com20020_dev *card, *tmpcard;
173+
struct com20020_priv *priv;
174+
175+
priv = pci_get_drvdata(pdev);
176+
177+
list_for_each_entry_safe(card, tmpcard, &priv->list_dev, list) {
178+
struct net_device *dev = card->dev;
179+
180+
unregister_netdev(dev);
181+
free_irq(dev->irq, dev);
182+
free_netdev(dev);
183+
}
143184
}
144185

145186
static struct com20020_pci_card_info card_info_10mbit = {

drivers/net/arcnet/com20020_cs.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,6 @@ static void com20020_detach(struct pcmcia_device *p_dev);
112112

113113
/*====================================================================*/
114114

115-
struct com20020_dev {
116-
struct net_device *dev;
117-
};
118-
119115
static int com20020_probe(struct pcmcia_device *p_dev)
120116
{
121117
struct com20020_dev *info;

include/linux/com20020.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ extern const struct net_device_ops com20020_netdev_ops;
4141
#define BUS_ALIGN 1
4242
#endif
4343

44-
#define PLX_PCI_MAX_CARDS 1
44+
#define PLX_PCI_MAX_CARDS 2
4545

4646
struct com20020_pci_channel_map {
4747
u32 bar;
@@ -58,6 +58,19 @@ struct com20020_pci_card_info {
5858
unsigned int flags;
5959
};
6060

61+
struct com20020_priv {
62+
struct com20020_pci_card_info *ci;
63+
struct list_head list_dev;
64+
};
65+
66+
struct com20020_dev {
67+
struct list_head list;
68+
struct net_device *dev;
69+
70+
struct com20020_priv *pci_priv;
71+
int index;
72+
};
73+
6174
#define _INTMASK (ioaddr+BUS_ALIGN*0) /* writable */
6275
#define _STATUS (ioaddr+BUS_ALIGN*0) /* readable */
6376
#define _COMMAND (ioaddr+BUS_ALIGN*1) /* standard arcnet commands */

0 commit comments

Comments
 (0)