aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-10-27 01:16:02 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-27 01:16:02 -0400
commit61b9da925a5e985afc268eb8184f1af3ef542422 (patch)
treef236a21ec42a998dfebd167b91bd1c610cbc7dc1
parent4b3418fba0fe819197e3359d5ddbef84ba2c59de (diff)
parent59fbcbc61e1f0fd9acdf3efb09faca0320049718 (diff)
Merge tag 'arcnet-for-4.4-rc1' of git://git.pengutronix.de/git/mgr/linux
Michael Grzeschik says: ==================== This series includes code simplifaction. The main changes are the correct xceiver handling (enable/disable) of the com20020 cards. The driver now handles link status change detection. The EAE PCI-ARCNET cards now make use of the rotary encoded subdevice indexing and got support for led triggers on transmit and reconnection events. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/arcnet/arcdevice.h21
-rw-r--r--drivers/net/arcnet/arcnet.c107
-rw-r--r--drivers/net/arcnet/com20020-pci.c107
-rw-r--r--drivers/net/arcnet/com20020.c39
-rw-r--r--drivers/net/arcnet/com20020.h14
-rw-r--r--include/linux/leds.h7
6 files changed, 277 insertions, 18 deletions
diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h
index d7fdea11e694..20bfb9ba83ea 100644
--- a/drivers/net/arcnet/arcdevice.h
+++ b/drivers/net/arcnet/arcdevice.h
@@ -237,6 +237,8 @@ struct Outgoing {
237 numsegs; /* number of segments */ 237 numsegs; /* number of segments */
238}; 238};
239 239
240#define ARCNET_LED_NAME_SZ (IFNAMSIZ + 6)
241
240struct arcnet_local { 242struct arcnet_local {
241 uint8_t config, /* current value of CONFIG register */ 243 uint8_t config, /* current value of CONFIG register */
242 timeout, /* Extended timeout for COM20020 */ 244 timeout, /* Extended timeout for COM20020 */
@@ -260,6 +262,13 @@ struct arcnet_local {
260 /* On preemtive and SMB a lock is needed */ 262 /* On preemtive and SMB a lock is needed */
261 spinlock_t lock; 263 spinlock_t lock;
262 264
265 struct led_trigger *tx_led_trig;
266 char tx_led_trig_name[ARCNET_LED_NAME_SZ];
267 struct led_trigger *recon_led_trig;
268 char recon_led_trig_name[ARCNET_LED_NAME_SZ];
269
270 struct timer_list timer;
271
263 /* 272 /*
264 * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of 273 * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of
265 * which can be used for either sending or receiving. The new dynamic 274 * which can be used for either sending or receiving. The new dynamic
@@ -309,6 +318,8 @@ struct arcnet_local {
309 int (*reset)(struct net_device *dev, int really_reset); 318 int (*reset)(struct net_device *dev, int really_reset);
310 void (*open)(struct net_device *dev); 319 void (*open)(struct net_device *dev);
311 void (*close)(struct net_device *dev); 320 void (*close)(struct net_device *dev);
321 void (*datatrigger) (struct net_device * dev, int enable);
322 void (*recontrigger) (struct net_device * dev, int enable);
312 323
313 void (*copy_to_card)(struct net_device *dev, int bufnum, 324 void (*copy_to_card)(struct net_device *dev, int bufnum,
314 int offset, void *buf, int count); 325 int offset, void *buf, int count);
@@ -319,6 +330,16 @@ struct arcnet_local {
319 void __iomem *mem_start; /* pointer to ioremap'ed MMIO */ 330 void __iomem *mem_start; /* pointer to ioremap'ed MMIO */
320}; 331};
321 332
333enum arcnet_led_event {
334 ARCNET_LED_EVENT_RECON,
335 ARCNET_LED_EVENT_OPEN,
336 ARCNET_LED_EVENT_STOP,
337 ARCNET_LED_EVENT_TX,
338};
339
340void arcnet_led_event(struct net_device *netdev, enum arcnet_led_event event);
341void devm_arcnet_led_init(struct net_device *netdev, int index, int subid);
342
322#if ARCNET_DEBUG_MAX & D_SKB 343#if ARCNET_DEBUG_MAX & D_SKB
323void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); 344void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc);
324#else 345#else
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index e41dd36fe832..6ea963e3b89a 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -52,6 +52,8 @@
52#include <linux/init.h> 52#include <linux/init.h>
53#include <linux/jiffies.h> 53#include <linux/jiffies.h>
54 54
55#include <linux/leds.h>
56
55#include "arcdevice.h" 57#include "arcdevice.h"
56#include "com9026.h" 58#include "com9026.h"
57 59
@@ -189,6 +191,71 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum,
189 191
190#endif 192#endif
191 193
194/* Trigger a LED event in response to a ARCNET device event */
195void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event)
196{
197 struct arcnet_local *lp = netdev_priv(dev);
198 unsigned long led_delay = 350;
199 unsigned long tx_delay = 50;
200
201 switch (event) {
202 case ARCNET_LED_EVENT_RECON:
203 led_trigger_blink_oneshot(lp->recon_led_trig,
204 &led_delay, &led_delay, 0);
205 break;
206 case ARCNET_LED_EVENT_OPEN:
207 led_trigger_event(lp->tx_led_trig, LED_OFF);
208 led_trigger_event(lp->recon_led_trig, LED_OFF);
209 break;
210 case ARCNET_LED_EVENT_STOP:
211 led_trigger_event(lp->tx_led_trig, LED_OFF);
212 led_trigger_event(lp->recon_led_trig, LED_OFF);
213 break;
214 case ARCNET_LED_EVENT_TX:
215 led_trigger_blink_oneshot(lp->tx_led_trig,
216 &tx_delay, &tx_delay, 0);
217 break;
218 }
219}
220EXPORT_SYMBOL_GPL(arcnet_led_event);
221
222static void arcnet_led_release(struct device *gendev, void *res)
223{
224 struct arcnet_local *lp = netdev_priv(to_net_dev(gendev));
225
226 led_trigger_unregister_simple(lp->tx_led_trig);
227 led_trigger_unregister_simple(lp->recon_led_trig);
228}
229
230/* Register ARCNET LED triggers for a arcnet device
231 *
232 * This is normally called from a driver's probe function
233 */
234void devm_arcnet_led_init(struct net_device *netdev, int index, int subid)
235{
236 struct arcnet_local *lp = netdev_priv(netdev);
237 void *res;
238
239 res = devres_alloc(arcnet_led_release, 0, GFP_KERNEL);
240 if (!res) {
241 netdev_err(netdev, "cannot register LED triggers\n");
242 return;
243 }
244
245 snprintf(lp->tx_led_trig_name, sizeof(lp->tx_led_trig_name),
246 "arc%d-%d-tx", index, subid);
247 snprintf(lp->recon_led_trig_name, sizeof(lp->recon_led_trig_name),
248 "arc%d-%d-recon", index, subid);
249
250 led_trigger_register_simple(lp->tx_led_trig_name,
251 &lp->tx_led_trig);
252 led_trigger_register_simple(lp->recon_led_trig_name,
253 &lp->recon_led_trig);
254
255 devres_add(&netdev->dev, res);
256}
257EXPORT_SYMBOL_GPL(devm_arcnet_led_init);
258
192/* Unregister a protocol driver from the arc_proto_map. Protocol drivers 259/* Unregister a protocol driver from the arc_proto_map. Protocol drivers
193 * are responsible for registering themselves, but the unregister routine 260 * are responsible for registering themselves, but the unregister routine
194 * is pretty generic so we'll do it here. 261 * is pretty generic so we'll do it here.
@@ -314,6 +381,16 @@ static void arcdev_setup(struct net_device *dev)
314 dev->flags = IFF_BROADCAST; 381 dev->flags = IFF_BROADCAST;
315} 382}
316 383
384static void arcnet_timer(unsigned long data)
385{
386 struct net_device *dev = (struct net_device *)data;
387
388 if (!netif_carrier_ok(dev)) {
389 netif_carrier_on(dev);
390 netdev_info(dev, "link up\n");
391 }
392}
393
317struct net_device *alloc_arcdev(const char *name) 394struct net_device *alloc_arcdev(const char *name)
318{ 395{
319 struct net_device *dev; 396 struct net_device *dev;
@@ -325,6 +402,9 @@ struct net_device *alloc_arcdev(const char *name)
325 struct arcnet_local *lp = netdev_priv(dev); 402 struct arcnet_local *lp = netdev_priv(dev);
326 403
327 spin_lock_init(&lp->lock); 404 spin_lock_init(&lp->lock);
405 init_timer(&lp->timer);
406 lp->timer.data = (unsigned long) dev;
407 lp->timer.function = arcnet_timer;
328 } 408 }
329 409
330 return dev; 410 return dev;
@@ -423,8 +503,11 @@ int arcnet_open(struct net_device *dev)
423 lp->hw.intmask(dev, lp->intmask); 503 lp->hw.intmask(dev, lp->intmask);
424 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); 504 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
425 505
506 netif_carrier_off(dev);
426 netif_start_queue(dev); 507 netif_start_queue(dev);
508 mod_timer(&lp->timer, jiffies + msecs_to_jiffies(1000));
427 509
510 arcnet_led_event(dev, ARCNET_LED_EVENT_OPEN);
428 return 0; 511 return 0;
429 512
430 out_module_put: 513 out_module_put:
@@ -438,7 +521,11 @@ int arcnet_close(struct net_device *dev)
438{ 521{
439 struct arcnet_local *lp = netdev_priv(dev); 522 struct arcnet_local *lp = netdev_priv(dev);
440 523
524 arcnet_led_event(dev, ARCNET_LED_EVENT_STOP);
525 del_timer_sync(&lp->timer);
526
441 netif_stop_queue(dev); 527 netif_stop_queue(dev);
528 netif_carrier_off(dev);
442 529
443 /* flush TX and disable RX */ 530 /* flush TX and disable RX */
444 lp->hw.intmask(dev, 0); 531 lp->hw.intmask(dev, 0);
@@ -515,7 +602,7 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
515 struct ArcProto *proto; 602 struct ArcProto *proto;
516 int txbuf; 603 int txbuf;
517 unsigned long flags; 604 unsigned long flags;
518 int freeskb, retval; 605 int retval;
519 606
520 arc_printk(D_DURING, dev, 607 arc_printk(D_DURING, dev,
521 "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", 608 "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
@@ -554,15 +641,13 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
554 * the package later - forget about it now 641 * the package later - forget about it now
555 */ 642 */
556 dev->stats.tx_bytes += skb->len; 643 dev->stats.tx_bytes += skb->len;
557 freeskb = 1; 644 dev_kfree_skb(skb);
558 } else { 645 } else {
559 /* do it the 'split' way */ 646 /* do it the 'split' way */
560 lp->outgoing.proto = proto; 647 lp->outgoing.proto = proto;
561 lp->outgoing.skb = skb; 648 lp->outgoing.skb = skb;
562 lp->outgoing.pkt = pkt; 649 lp->outgoing.pkt = pkt;
563 650
564 freeskb = 0;
565
566 if (proto->continue_tx && 651 if (proto->continue_tx &&
567 proto->continue_tx(dev, txbuf)) { 652 proto->continue_tx(dev, txbuf)) {
568 arc_printk(D_NORMAL, dev, 653 arc_printk(D_NORMAL, dev,
@@ -574,7 +659,6 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
574 lp->next_tx = txbuf; 659 lp->next_tx = txbuf;
575 } else { 660 } else {
576 retval = NETDEV_TX_BUSY; 661 retval = NETDEV_TX_BUSY;
577 freeskb = 0;
578 } 662 }
579 663
580 arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", 664 arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n",
@@ -588,10 +672,9 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
588 arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", 672 arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n",
589 __FILE__, __LINE__, __func__, lp->hw.status(dev)); 673 __FILE__, __LINE__, __func__, lp->hw.status(dev));
590 674
591 spin_unlock_irqrestore(&lp->lock, flags); 675 arcnet_led_event(dev, ARCNET_LED_EVENT_TX);
592 if (freeskb)
593 dev_kfree_skb(skb);
594 676
677 spin_unlock_irqrestore(&lp->lock, flags);
595 return retval; /* no need to try again */ 678 return retval; /* no need to try again */
596} 679}
597EXPORT_SYMBOL(arcnet_send_packet); 680EXPORT_SYMBOL(arcnet_send_packet);
@@ -843,6 +926,13 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
843 926
844 arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n", 927 arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n",
845 status); 928 status);
929 if (netif_carrier_ok(dev)) {
930 netif_carrier_off(dev);
931 netdev_info(dev, "link down\n");
932 }
933 mod_timer(&lp->timer, jiffies + msecs_to_jiffies(1000));
934
935 arcnet_led_event(dev, ARCNET_LED_EVENT_RECON);
846 /* MYRECON bit is at bit 7 of diagstatus */ 936 /* MYRECON bit is at bit 7 of diagstatus */
847 if (diagstatus & 0x80) 937 if (diagstatus & 0x80)
848 arc_printk(D_RECON, dev, "Put out that recon myself\n"); 938 arc_printk(D_RECON, dev, "Put out that recon myself\n");
@@ -893,6 +983,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
893 lp->num_recons = lp->network_down = 0; 983 lp->num_recons = lp->network_down = 0;
894 984
895 arc_printk(D_DURING, dev, "not recon: clearing counters anyway.\n"); 985 arc_printk(D_DURING, dev, "not recon: clearing counters anyway.\n");
986 netif_carrier_on(dev);
896 } 987 }
897 988
898 if (didsomething) 989 if (didsomething)
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index a12bf83be750..239de38fbd6a 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -41,6 +41,7 @@
41#include <linux/pci.h> 41#include <linux/pci.h>
42#include <linux/list.h> 42#include <linux/list.h>
43#include <linux/io.h> 43#include <linux/io.h>
44#include <linux/leds.h>
44 45
45#include "arcdevice.h" 46#include "arcdevice.h"
46#include "com20020.h" 47#include "com20020.h"
@@ -62,12 +63,43 @@ module_param(clockp, int, 0);
62module_param(clockm, int, 0); 63module_param(clockm, int, 0);
63MODULE_LICENSE("GPL"); 64MODULE_LICENSE("GPL");
64 65
66static void led_tx_set(struct led_classdev *led_cdev,
67 enum led_brightness value)
68{
69 struct com20020_dev *card;
70 struct com20020_priv *priv;
71 struct com20020_pci_card_info *ci;
72
73 card = container_of(led_cdev, struct com20020_dev, tx_led);
74
75 priv = card->pci_priv;
76 ci = priv->ci;
77
78 outb(!!value, priv->misc + ci->leds[card->index].green);
79}
80
81static void led_recon_set(struct led_classdev *led_cdev,
82 enum led_brightness value)
83{
84 struct com20020_dev *card;
85 struct com20020_priv *priv;
86 struct com20020_pci_card_info *ci;
87
88 card = container_of(led_cdev, struct com20020_dev, recon_led);
89
90 priv = card->pci_priv;
91 ci = priv->ci;
92
93 outb(!!value, priv->misc + ci->leds[card->index].red);
94}
95
65static void com20020pci_remove(struct pci_dev *pdev); 96static void com20020pci_remove(struct pci_dev *pdev);
66 97
67static int com20020pci_probe(struct pci_dev *pdev, 98static int com20020pci_probe(struct pci_dev *pdev,
68 const struct pci_device_id *id) 99 const struct pci_device_id *id)
69{ 100{
70 struct com20020_pci_card_info *ci; 101 struct com20020_pci_card_info *ci;
102 struct com20020_pci_channel_map *mm;
71 struct net_device *dev; 103 struct net_device *dev;
72 struct arcnet_local *lp; 104 struct arcnet_local *lp;
73 struct com20020_priv *priv; 105 struct com20020_priv *priv;
@@ -84,9 +116,22 @@ static int com20020pci_probe(struct pci_dev *pdev,
84 116
85 ci = (struct com20020_pci_card_info *)id->driver_data; 117 ci = (struct com20020_pci_card_info *)id->driver_data;
86 priv->ci = ci; 118 priv->ci = ci;
119 mm = &ci->misc_map;
87 120
88 INIT_LIST_HEAD(&priv->list_dev); 121 INIT_LIST_HEAD(&priv->list_dev);
89 122
123 if (mm->size) {
124 ioaddr = pci_resource_start(pdev, mm->bar) + mm->offset;
125 r = devm_request_region(&pdev->dev, ioaddr, mm->size,
126 "com20020-pci");
127 if (!r) {
128 pr_err("IO region %xh-%xh already allocated.\n",
129 ioaddr, ioaddr + mm->size - 1);
130 return -EBUSY;
131 }
132 priv->misc = ioaddr;
133 }
134
90 for (i = 0; i < ci->devcount; i++) { 135 for (i = 0; i < ci->devcount; i++) {
91 struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i]; 136 struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
92 struct com20020_dev *card; 137 struct com20020_dev *card;
@@ -96,6 +141,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
96 ret = -ENOMEM; 141 ret = -ENOMEM;
97 goto out_port; 142 goto out_port;
98 } 143 }
144 dev->dev_port = i;
99 145
100 dev->netdev_ops = &com20020_netdev_ops; 146 dev->netdev_ops = &com20020_netdev_ops;
101 147
@@ -131,6 +177,13 @@ static int com20020pci_probe(struct pci_dev *pdev,
131 lp->timeout = timeout; 177 lp->timeout = timeout;
132 lp->hw.owner = THIS_MODULE; 178 lp->hw.owner = THIS_MODULE;
133 179
180 /* Get the dev_id from the PLX rotary coder */
181 if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
182 dev->dev_id = 0xc;
183 dev->dev_id ^= inb(priv->misc + ci->rotary) >> 4;
184
185 snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
186
134 if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) { 187 if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
135 pr_err("IO address %Xh is empty!\n", ioaddr); 188 pr_err("IO address %Xh is empty!\n", ioaddr);
136 ret = -EIO; 189 ret = -EIO;
@@ -148,14 +201,41 @@ static int com20020pci_probe(struct pci_dev *pdev,
148 201
149 card->index = i; 202 card->index = i;
150 card->pci_priv = priv; 203 card->pci_priv = priv;
204 card->tx_led.brightness_set = led_tx_set;
205 card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
206 GFP_KERNEL, "arc%d-%d-tx",
207 dev->dev_id, i);
208 card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
209 "pci:green:tx:%d-%d",
210 dev->dev_id, i);
211
212 card->tx_led.dev = &dev->dev;
213 card->recon_led.brightness_set = led_recon_set;
214 card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
215 GFP_KERNEL, "arc%d-%d-recon",
216 dev->dev_id, i);
217 card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
218 "pci:red:recon:%d-%d",
219 dev->dev_id, i);
220 card->recon_led.dev = &dev->dev;
151 card->dev = dev; 221 card->dev = dev;
152 222
223 ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
224 if (ret)
225 goto out_port;
226
227 ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
228 if (ret)
229 goto out_port;
230
153 dev_set_drvdata(&dev->dev, card); 231 dev_set_drvdata(&dev->dev, card);
154 232
155 ret = com20020_found(dev, IRQF_SHARED); 233 ret = com20020_found(dev, IRQF_SHARED);
156 if (ret) 234 if (ret)
157 goto out_port; 235 goto out_port;
158 236
237 devm_arcnet_led_init(dev, dev->dev_id, i);
238
159 list_add(&card->list, &priv->list_dev); 239 list_add(&card->list, &priv->list_dev);
160 } 240 }
161 241
@@ -234,6 +314,18 @@ static struct com20020_pci_card_info card_info_eae_arc1 = {
234 .size = 0x08, 314 .size = 0x08,
235 }, 315 },
236 }, 316 },
317 .misc_map = {
318 .bar = 2,
319 .offset = 0x10,
320 .size = 0x04,
321 },
322 .leds = {
323 {
324 .green = 0x0,
325 .red = 0x1,
326 },
327 },
328 .rotary = 0x0,
237 .flags = ARC_CAN_10MBIT, 329 .flags = ARC_CAN_10MBIT,
238}; 330};
239 331
@@ -251,6 +343,21 @@ static struct com20020_pci_card_info card_info_eae_ma1 = {
251 .size = 0x08, 343 .size = 0x08,
252 } 344 }
253 }, 345 },
346 .misc_map = {
347 .bar = 2,
348 .offset = 0x10,
349 .size = 0x04,
350 },
351 .leds = {
352 {
353 .green = 0x0,
354 .red = 0x1,
355 }, {
356 .green = 0x2,
357 .red = 0x3,
358 },
359 },
360 .rotary = 0x0,
254 .flags = ARC_CAN_10MBIT, 361 .flags = ARC_CAN_10MBIT,
255}; 362};
256 363
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index c82f323a8c2b..13d9ad4b3f5c 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -118,7 +118,7 @@ int com20020_check(struct net_device *dev)
118 arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND); 118 arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND);
119 } 119 }
120 120
121 lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE; 121 lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE;
122 /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */ 122 /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */
123 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); 123 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
124 arcnet_outb(0x42, ioaddr, COM20020_REG_W_XREG); 124 arcnet_outb(0x42, ioaddr, COM20020_REG_W_XREG);
@@ -131,11 +131,6 @@ int com20020_check(struct net_device *dev)
131 } 131 }
132 arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status); 132 arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status);
133 133
134 /* Enable TX */
135 lp->config |= TXENcfg;
136 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
137 arcnet_outb(arcnet_inb(ioaddr, 8), ioaddr, COM20020_REG_W_XREG);
138
139 arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear, 134 arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
140 ioaddr, COM20020_REG_W_COMMAND); 135 ioaddr, COM20020_REG_W_COMMAND);
141 status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS); 136 status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS);
@@ -169,9 +164,33 @@ static int com20020_set_hwaddr(struct net_device *dev, void *addr)
169 return 0; 164 return 0;
170} 165}
171 166
167static int com20020_netdev_open(struct net_device *dev)
168{
169 int ioaddr = dev->base_addr;
170 struct arcnet_local *lp = netdev_priv(dev);
171
172 lp->config |= TXENcfg;
173 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
174
175 return arcnet_open(dev);
176}
177
178static int com20020_netdev_close(struct net_device *dev)
179{
180 int ioaddr = dev->base_addr;
181 struct arcnet_local *lp = netdev_priv(dev);
182
183 arcnet_close(dev);
184
185 /* disable transmitter */
186 lp->config &= ~TXENcfg;
187 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
188 return 0;
189}
190
172const struct net_device_ops com20020_netdev_ops = { 191const struct net_device_ops com20020_netdev_ops = {
173 .ndo_open = arcnet_open, 192 .ndo_open = com20020_netdev_open,
174 .ndo_stop = arcnet_close, 193 .ndo_stop = com20020_netdev_close,
175 .ndo_start_xmit = arcnet_send_packet, 194 .ndo_start_xmit = arcnet_send_packet,
176 .ndo_tx_timeout = arcnet_timeout, 195 .ndo_tx_timeout = arcnet_timeout,
177 .ndo_set_mac_address = com20020_set_hwaddr, 196 .ndo_set_mac_address = com20020_set_hwaddr,
@@ -215,7 +234,7 @@ int com20020_found(struct net_device *dev, int shared)
215 arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND); 234 arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND);
216 } 235 }
217 236
218 lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE; 237 lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE;
219 /* Default 0x38 + register: Node ID */ 238 /* Default 0x38 + register: Node ID */
220 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); 239 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
221 arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG); 240 arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG);
@@ -274,7 +293,7 @@ static int com20020_reset(struct net_device *dev, int really_reset)
274 dev->name, arcnet_inb(ioaddr, COM20020_REG_R_STATUS)); 293 dev->name, arcnet_inb(ioaddr, COM20020_REG_R_STATUS));
275 294
276 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); 295 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
277 lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2); 296 lp->config |= (lp->timeout << 3) | (lp->backplane << 2);
278 /* power-up defaults */ 297 /* power-up defaults */
279 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); 298 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
280 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); 299 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
diff --git a/drivers/net/arcnet/com20020.h b/drivers/net/arcnet/com20020.h
index 22a460f39fb9..0bcc5d0a6903 100644
--- a/drivers/net/arcnet/com20020.h
+++ b/drivers/net/arcnet/com20020.h
@@ -26,6 +26,7 @@
26 */ 26 */
27#ifndef __COM20020_H 27#ifndef __COM20020_H
28#define __COM20020_H 28#define __COM20020_H
29#include <linux/leds.h>
29 30
30int com20020_check(struct net_device *dev); 31int com20020_check(struct net_device *dev);
31int com20020_found(struct net_device *dev, int shared); 32int com20020_found(struct net_device *dev, int shared);
@@ -36,6 +37,11 @@ extern const struct net_device_ops com20020_netdev_ops;
36 37
37#define PLX_PCI_MAX_CARDS 2 38#define PLX_PCI_MAX_CARDS 2
38 39
40struct ledoffsets {
41 int green;
42 int red;
43};
44
39struct com20020_pci_channel_map { 45struct com20020_pci_channel_map {
40 u32 bar; 46 u32 bar;
41 u32 offset; 47 u32 offset;
@@ -47,6 +53,10 @@ struct com20020_pci_card_info {
47 int devcount; 53 int devcount;
48 54
49 struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS]; 55 struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS];
56 struct com20020_pci_channel_map misc_map;
57
58 struct ledoffsets leds[PLX_PCI_MAX_CARDS];
59 int rotary;
50 60
51 unsigned int flags; 61 unsigned int flags;
52}; 62};
@@ -54,12 +64,16 @@ struct com20020_pci_card_info {
54struct com20020_priv { 64struct com20020_priv {
55 struct com20020_pci_card_info *ci; 65 struct com20020_pci_card_info *ci;
56 struct list_head list_dev; 66 struct list_head list_dev;
67 resource_size_t misc;
57}; 68};
58 69
59struct com20020_dev { 70struct com20020_dev {
60 struct list_head list; 71 struct list_head list;
61 struct net_device *dev; 72 struct net_device *dev;
62 73
74 struct led_classdev tx_led;
75 struct led_classdev recon_led;
76
63 struct com20020_priv *pci_priv; 77 struct com20020_priv *pci_priv;
64 int index; 78 int index;
65}; 79};
diff --git a/include/linux/leds.h b/include/linux/leds.h
index b122eeafb5dc..fa359c79c825 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -283,6 +283,13 @@ static inline void led_trigger_register_simple(const char *name,
283static inline void led_trigger_unregister_simple(struct led_trigger *trigger) {} 283static inline void led_trigger_unregister_simple(struct led_trigger *trigger) {}
284static inline void led_trigger_event(struct led_trigger *trigger, 284static inline void led_trigger_event(struct led_trigger *trigger,
285 enum led_brightness event) {} 285 enum led_brightness event) {}
286static inline void led_trigger_blink(struct led_trigger *trigger,
287 unsigned long *delay_on,
288 unsigned long *delay_off) {}
289static inline void led_trigger_blink_oneshot(struct led_trigger *trigger,
290 unsigned long *delay_on,
291 unsigned long *delay_off,
292 int invert) {}
286static inline void led_trigger_set_default(struct led_classdev *led_cdev) {} 293static inline void led_trigger_set_default(struct led_classdev *led_cdev) {}
287static inline void led_trigger_set(struct led_classdev *led_cdev, 294static inline void led_trigger_set(struct led_classdev *led_cdev,
288 struct led_trigger *trigger) {} 295 struct led_trigger *trigger) {}