aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-09-29 14:36:33 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-29 14:36:33 -0400
commit2b7fc477b0423cbcc7be8ad8652e3552198de418 (patch)
tree58f6e51300fb344252e171ce4b167498e6be81e3
parent41c91996d99394a75912aa5bfda300b85789ed43 (diff)
parent5b85bad2a473a8b90cac93d21ab024ba221a8b09 (diff)
Merge branch 'arcnet-EAE'
Michael Grzeschik says: ==================== ARCNET: add support for EAE multi interfac card this series adds support for the PLX Bridge based multi interface pci cards and adds support to change device address on com200xx chips during runtime. This series is based on v3.17-rc7. It is fixed for build against com20020_cs. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/arcnet/arcnet.c2
-rw-r--r--drivers/net/arcnet/com20020-pci.c369
-rw-r--r--drivers/net/arcnet/com20020.c14
-rw-r--r--drivers/net/arcnet/com20020_cs.c4
-rw-r--r--include/linux/com20020.h29
5 files changed, 330 insertions, 88 deletions
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 3b790de6c976..09de683c167e 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -777,7 +777,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
777 ACOMMAND(CFLAGScmd | RESETclear); 777 ACOMMAND(CFLAGScmd | RESETclear);
778 AINTMASK(0); 778 AINTMASK(0);
779 spin_unlock(&lp->lock); 779 spin_unlock(&lp->lock);
780 return IRQ_HANDLED; 780 return retval;
781 } 781 }
782 782
783 BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", 783 BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 7bb292e59559..6c99ff0b0bdd 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -38,6 +38,7 @@
38#include <linux/pci.h> 38#include <linux/pci.h>
39#include <linux/arcdevice.h> 39#include <linux/arcdevice.h>
40#include <linux/com20020.h> 40#include <linux/com20020.h>
41#include <linux/list.h>
41 42
42#include <asm/io.h> 43#include <asm/io.h>
43 44
@@ -61,115 +62,317 @@ module_param(clockp, int, 0);
61module_param(clockm, int, 0); 62module_param(clockm, int, 0);
62MODULE_LICENSE("GPL"); 63MODULE_LICENSE("GPL");
63 64
65static void com20020pci_remove(struct pci_dev *pdev);
66
64static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 67static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
65{ 68{
69 struct com20020_pci_card_info *ci;
66 struct net_device *dev; 70 struct net_device *dev;
67 struct arcnet_local *lp; 71 struct arcnet_local *lp;
68 int ioaddr, err; 72 struct com20020_priv *priv;
73 int i, ioaddr, ret;
74 struct resource *r;
69 75
70 if (pci_enable_device(pdev)) 76 if (pci_enable_device(pdev))
71 return -EIO; 77 return -EIO;
72 dev = alloc_arcdev(device);
73 if (!dev)
74 return -ENOMEM;
75 78
76 dev->netdev_ops = &com20020_netdev_ops; 79 priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv),
80 GFP_KERNEL);
81 ci = (struct com20020_pci_card_info *)id->driver_data;
82 priv->ci = ci;
77 83
78 lp = netdev_priv(dev); 84 INIT_LIST_HEAD(&priv->list_dev);
79 85
80 pci_set_drvdata(pdev, dev);
81 86
82 // SOHARD needs PCI base addr 4 87 for (i = 0; i < ci->devcount; i++) {
83 if (pdev->vendor==0x10B5) { 88 struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
84 BUGMSG(D_NORMAL, "SOHARD\n"); 89 struct com20020_dev *card;
85 ioaddr = pci_resource_start(pdev, 4);
86 }
87 else {
88 BUGMSG(D_NORMAL, "Contemporary Controls\n");
89 ioaddr = pci_resource_start(pdev, 2);
90 }
91 90
92 if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com20020-pci")) { 91 dev = alloc_arcdev(device);
93 BUGMSG(D_INIT, "IO region %xh-%xh already allocated.\n", 92 if (!dev) {
94 ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); 93 ret = -ENOMEM;
95 err = -EBUSY; 94 goto out_port;
96 goto out_dev; 95 }
97 }
98 96
99 // Dummy access after Reset 97 dev->netdev_ops = &com20020_netdev_ops;
100 // ARCNET controller needs this access to detect bustype 98
101 outb(0x00,ioaddr+1); 99 lp = netdev_priv(dev);
102 inb(ioaddr+1); 100
103 101 BUGMSG(D_NORMAL, "%s Controls\n", ci->name);
104 dev->base_addr = ioaddr; 102 ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
105 dev->irq = pdev->irq; 103
106 dev->dev_addr[0] = node; 104 r = devm_request_region(&pdev->dev, ioaddr, cm->size,
107 lp->card_name = "PCI COM20020"; 105 "com20020-pci");
108 lp->card_flags = id->driver_data; 106 if (!r) {
109 lp->backplane = backplane; 107 pr_err("IO region %xh-%xh already allocated.\n",
110 lp->clockp = clockp & 7; 108 ioaddr, ioaddr + cm->size - 1);
111 lp->clockm = clockm & 3; 109 ret = -EBUSY;
112 lp->timeout = timeout; 110 goto out_port;
113 lp->hw.owner = THIS_MODULE; 111 }
114 112
115 if (ASTATUS() == 0xFF) { 113 /* Dummy access after Reset
116 BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, " 114 * ARCNET controller needs
117 "but seems empty!\n", ioaddr); 115 * this access to detect bustype
118 err = -EIO; 116 */
119 goto out_port; 117 outb(0x00, ioaddr + 1);
120 } 118 inb(ioaddr + 1);
121 if (com20020_check(dev)) { 119
122 err = -EIO; 120 dev->base_addr = ioaddr;
123 goto out_port; 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);
124 } 159 }
125 160
126 if ((err = com20020_found(dev, IRQF_SHARED)) != 0) 161 pci_set_drvdata(pdev, priv);
127 goto out_port;
128 162
129 return 0; 163 return 0;
130 164
131out_port: 165out_port:
132 release_region(ioaddr, ARCNET_TOTAL_SIZE); 166 com20020pci_remove(pdev);
133out_dev: 167 return ret;
134 free_netdev(dev);
135 return err;
136} 168}
137 169
138static void com20020pci_remove(struct pci_dev *pdev) 170static void com20020pci_remove(struct pci_dev *pdev)
139{ 171{
140 struct net_device *dev = pci_get_drvdata(pdev); 172 struct com20020_dev *card, *tmpcard;
141 unregister_netdev(dev); 173 struct com20020_priv *priv;
142 free_irq(dev->irq, dev); 174
143 release_region(dev->base_addr, ARCNET_TOTAL_SIZE); 175 priv = pci_get_drvdata(pdev);
144 free_netdev(dev); 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 }
145} 184}
146 185
186static struct com20020_pci_card_info card_info_10mbit = {
187 .name = "ARC-PCI",
188 .devcount = 1,
189 .chan_map_tbl = {
190 { 2, 0x00, 0x08 },
191 },
192 .flags = ARC_CAN_10MBIT,
193};
194
195static struct com20020_pci_card_info card_info_5mbit = {
196 .name = "ARC-PCI",
197 .devcount = 1,
198 .chan_map_tbl = {
199 { 2, 0x00, 0x08 },
200 },
201 .flags = ARC_IS_5MBIT,
202};
203
204static struct com20020_pci_card_info card_info_sohard = {
205 .name = "PLX-PCI",
206 .devcount = 1,
207 /* SOHARD needs PCI base addr 4 */
208 .chan_map_tbl = {
209 {4, 0x00, 0x08},
210 },
211 .flags = ARC_CAN_10MBIT,
212};
213
214static struct com20020_pci_card_info card_info_eae = {
215 .name = "EAE PLX-PCI",
216 .devcount = 2,
217 .chan_map_tbl = {
218 { 2, 0x00, 0x08 },
219 { 2, 0x08, 0x08 }
220 },
221 .flags = ARC_CAN_10MBIT,
222};
223
147static const struct pci_device_id com20020pci_id_table[] = { 224static const struct pci_device_id com20020pci_id_table[] = {
148 { 0x1571, 0xa001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 225 {
149 { 0x1571, 0xa002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 226 0x1571, 0xa001,
150 { 0x1571, 0xa003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 227 PCI_ANY_ID, PCI_ANY_ID,
151 { 0x1571, 0xa004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 228 0, 0,
152 { 0x1571, 0xa005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 229 0,
153 { 0x1571, 0xa006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 230 },
154 { 0x1571, 0xa007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 231 {
155 { 0x1571, 0xa008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 232 0x1571, 0xa002,
156 { 0x1571, 0xa009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 233 PCI_ANY_ID, PCI_ANY_ID,
157 { 0x1571, 0xa00a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 234 0, 0,
158 { 0x1571, 0xa00b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 235 0,
159 { 0x1571, 0xa00c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 236 },
160 { 0x1571, 0xa00d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 237 {
161 { 0x1571, 0xa00e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 238 0x1571, 0xa003,
162 { 0x1571, 0xa201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 239 PCI_ANY_ID, PCI_ANY_ID,
163 { 0x1571, 0xa202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 240 0, 0,
164 { 0x1571, 0xa203, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 241 0
165 { 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 242 },
166 { 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 243 {
167 { 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 244 0x1571, 0xa004,
168 { 0x10B5, 0x9030, 0x10B5, 0x2978, 0, 0, ARC_CAN_10MBIT }, 245 PCI_ANY_ID, PCI_ANY_ID,
169 { 0x10B5, 0x9050, 0x10B5, 0x2273, 0, 0, ARC_CAN_10MBIT }, 246 0, 0,
170 { 0x14BA, 0x6000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 247 0,
171 { 0x10B5, 0x2200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 248 },
172 {0,} 249 {
250 0x1571, 0xa005,
251 PCI_ANY_ID, PCI_ANY_ID,
252 0, 0,
253 0
254 },
255 {
256 0x1571, 0xa006,
257 PCI_ANY_ID, PCI_ANY_ID,
258 0, 0,
259 0
260 },
261 {
262 0x1571, 0xa007,
263 PCI_ANY_ID, PCI_ANY_ID,
264 0, 0,
265 0
266 },
267 {
268 0x1571, 0xa008,
269 PCI_ANY_ID, PCI_ANY_ID,
270 0, 0,
271 0
272 },
273 {
274 0x1571, 0xa009,
275 PCI_ANY_ID, PCI_ANY_ID,
276 0, 0,
277 (kernel_ulong_t)&card_info_5mbit
278 },
279 {
280 0x1571, 0xa00a,
281 PCI_ANY_ID, PCI_ANY_ID,
282 0, 0,
283 (kernel_ulong_t)&card_info_5mbit
284 },
285 {
286 0x1571, 0xa00b,
287 PCI_ANY_ID, PCI_ANY_ID,
288 0, 0,
289 (kernel_ulong_t)&card_info_5mbit
290 },
291 {
292 0x1571, 0xa00c,
293 PCI_ANY_ID, PCI_ANY_ID,
294 0, 0,
295 (kernel_ulong_t)&card_info_5mbit
296 },
297 {
298 0x1571, 0xa00d,
299 PCI_ANY_ID, PCI_ANY_ID,
300 0, 0,
301 (kernel_ulong_t)&card_info_5mbit
302 },
303 {
304 0x1571, 0xa00e,
305 PCI_ANY_ID, PCI_ANY_ID,
306 0, 0,
307 (kernel_ulong_t)&card_info_5mbit
308 },
309 {
310 0x1571, 0xa201,
311 PCI_ANY_ID, PCI_ANY_ID,
312 0, 0,
313 (kernel_ulong_t)&card_info_10mbit
314 },
315 {
316 0x1571, 0xa202,
317 PCI_ANY_ID, PCI_ANY_ID,
318 0, 0,
319 (kernel_ulong_t)&card_info_10mbit
320 },
321 {
322 0x1571, 0xa203,
323 PCI_ANY_ID, PCI_ANY_ID,
324 0, 0,
325 (kernel_ulong_t)&card_info_10mbit
326 },
327 {
328 0x1571, 0xa204,
329 PCI_ANY_ID, PCI_ANY_ID,
330 0, 0,
331 (kernel_ulong_t)&card_info_10mbit
332 },
333 {
334 0x1571, 0xa205,
335 PCI_ANY_ID, PCI_ANY_ID,
336 0, 0,
337 (kernel_ulong_t)&card_info_10mbit
338 },
339 {
340 0x1571, 0xa206,
341 PCI_ANY_ID, PCI_ANY_ID,
342 0, 0,
343 (kernel_ulong_t)&card_info_10mbit
344 },
345 {
346 0x10B5, 0x9030,
347 0x10B5, 0x2978,
348 0, 0,
349 (kernel_ulong_t)&card_info_sohard
350 },
351 {
352 0x10B5, 0x9050,
353 0x10B5, 0x2273,
354 0, 0,
355 (kernel_ulong_t)&card_info_sohard
356 },
357 {
358 0x10B5, 0x9050,
359 0x10B5, 0x3292,
360 0, 0,
361 (kernel_ulong_t)&card_info_eae
362 },
363 {
364 0x14BA, 0x6000,
365 PCI_ANY_ID, PCI_ANY_ID,
366 0, 0,
367 (kernel_ulong_t)&card_info_10mbit
368 },
369 {
370 0x10B5, 0x2200,
371 PCI_ANY_ID, PCI_ANY_ID,
372 0, 0,
373 (kernel_ulong_t)&card_info_10mbit
374 },
375 { 0, }
173}; 376};
174 377
175MODULE_DEVICE_TABLE(pci, com20020pci_id_table); 378MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index 7b96c5f47e8d..1a8437842fbc 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -149,11 +149,25 @@ int com20020_check(struct net_device *dev)
149 return 0; 149 return 0;
150} 150}
151 151
152static int com20020_set_hwaddr(struct net_device *dev, void *addr)
153{
154 int ioaddr = dev->base_addr;
155 struct arcnet_local *lp = netdev_priv(dev);
156 struct sockaddr *hwaddr = addr;
157
158 memcpy(dev->dev_addr, hwaddr->sa_data, 1);
159 SET_SUBADR(SUB_NODE);
160 outb(dev->dev_addr[0], _XREG);
161
162 return 0;
163}
164
152const struct net_device_ops com20020_netdev_ops = { 165const struct net_device_ops com20020_netdev_ops = {
153 .ndo_open = arcnet_open, 166 .ndo_open = arcnet_open,
154 .ndo_stop = arcnet_close, 167 .ndo_stop = arcnet_close,
155 .ndo_start_xmit = arcnet_send_packet, 168 .ndo_start_xmit = arcnet_send_packet,
156 .ndo_tx_timeout = arcnet_timeout, 169 .ndo_tx_timeout = arcnet_timeout,
170 .ndo_set_mac_address = com20020_set_hwaddr,
157 .ndo_set_rx_mode = com20020_set_mc_list, 171 .ndo_set_rx_mode = com20020_set_mc_list,
158}; 172};
159 173
diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c
index 1a790a20210d..057d9582132a 100644
--- a/drivers/net/arcnet/com20020_cs.c
+++ b/drivers/net/arcnet/com20020_cs.c
@@ -112,10 +112,6 @@ static void com20020_detach(struct pcmcia_device *p_dev);
112 112
113/*====================================================================*/ 113/*====================================================================*/
114 114
115struct com20020_dev {
116 struct net_device *dev;
117};
118
119static int com20020_probe(struct pcmcia_device *p_dev) 115static int com20020_probe(struct pcmcia_device *p_dev)
120{ 116{
121 struct com20020_dev *info; 117 struct com20020_dev *info;
diff --git a/include/linux/com20020.h b/include/linux/com20020.h
index 5dcfb944b6ce..85898995b234 100644
--- a/include/linux/com20020.h
+++ b/include/linux/com20020.h
@@ -41,6 +41,35 @@ extern const struct net_device_ops com20020_netdev_ops;
41#define BUS_ALIGN 1 41#define BUS_ALIGN 1
42#endif 42#endif
43 43
44#define PLX_PCI_MAX_CARDS 2
45
46struct com20020_pci_channel_map {
47 u32 bar;
48 u32 offset;
49 u32 size; /* 0x00 - auto, e.g. length of entire bar */
50};
51
52struct com20020_pci_card_info {
53 const char *name;
54 int devcount;
55
56 struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS];
57
58 unsigned int flags;
59};
60
61struct com20020_priv {
62 struct com20020_pci_card_info *ci;
63 struct list_head list_dev;
64};
65
66struct com20020_dev {
67 struct list_head list;
68 struct net_device *dev;
69
70 struct com20020_priv *pci_priv;
71 int index;
72};
44 73
45#define _INTMASK (ioaddr+BUS_ALIGN*0) /* writable */ 74#define _INTMASK (ioaddr+BUS_ALIGN*0) /* writable */
46#define _STATUS (ioaddr+BUS_ALIGN*0) /* readable */ 75#define _STATUS (ioaddr+BUS_ALIGN*0) /* readable */