Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arcnet: com20020-pci: add led trigger support

The EAE PLX-PCI card has special leds on the the main io pci resource
bar. This patch adds support to trigger the conflict and data leds with
the packages.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

+181
+19
drivers/net/arcnet/arcdevice.h
··· 237 237 numsegs; /* number of segments */ 238 238 }; 239 239 240 + #define ARCNET_LED_NAME_SZ (IFNAMSIZ + 6) 241 + 240 242 struct arcnet_local { 241 243 uint8_t config, /* current value of CONFIG register */ 242 244 timeout, /* Extended timeout for COM20020 */ ··· 261 259 262 260 /* On preemtive and SMB a lock is needed */ 263 261 spinlock_t lock; 262 + 263 + struct led_trigger *tx_led_trig; 264 + char tx_led_trig_name[ARCNET_LED_NAME_SZ]; 265 + struct led_trigger *recon_led_trig; 266 + char recon_led_trig_name[ARCNET_LED_NAME_SZ]; 264 267 265 268 /* 266 269 * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of ··· 316 309 int (*reset)(struct net_device *dev, int really_reset); 317 310 void (*open)(struct net_device *dev); 318 311 void (*close)(struct net_device *dev); 312 + void (*datatrigger) (struct net_device * dev, int enable); 313 + void (*recontrigger) (struct net_device * dev, int enable); 319 314 320 315 void (*copy_to_card)(struct net_device *dev, int bufnum, 321 316 int offset, void *buf, int count); ··· 327 318 328 319 void __iomem *mem_start; /* pointer to ioremap'ed MMIO */ 329 320 }; 321 + 322 + enum arcnet_led_event { 323 + ARCNET_LED_EVENT_RECON, 324 + ARCNET_LED_EVENT_OPEN, 325 + ARCNET_LED_EVENT_STOP, 326 + ARCNET_LED_EVENT_TX, 327 + }; 328 + 329 + void arcnet_led_event(struct net_device *netdev, enum arcnet_led_event event); 330 + void devm_arcnet_led_init(struct net_device *netdev, int index, int subid); 330 331 331 332 #if ARCNET_DEBUG_MAX & D_SKB 332 333 void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc);
+72
drivers/net/arcnet/arcnet.c
··· 52 52 #include <linux/init.h> 53 53 #include <linux/jiffies.h> 54 54 55 + #include <linux/leds.h> 56 + 55 57 #include "arcdevice.h" 56 58 #include "com9026.h" 57 59 ··· 190 188 #define arcnet_dump_packet(dev, bufnum, desc, take_arcnet_lock) do { } while (0) 191 189 192 190 #endif 191 + 192 + /* Trigger a LED event in response to a ARCNET device event */ 193 + void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event) 194 + { 195 + struct arcnet_local *lp = netdev_priv(dev); 196 + unsigned long led_delay = 350; 197 + unsigned long tx_delay = 50; 198 + 199 + switch (event) { 200 + case ARCNET_LED_EVENT_RECON: 201 + led_trigger_blink_oneshot(lp->recon_led_trig, 202 + &led_delay, &led_delay, 0); 203 + break; 204 + case ARCNET_LED_EVENT_OPEN: 205 + led_trigger_event(lp->tx_led_trig, LED_OFF); 206 + led_trigger_event(lp->recon_led_trig, LED_OFF); 207 + break; 208 + case ARCNET_LED_EVENT_STOP: 209 + led_trigger_event(lp->tx_led_trig, LED_OFF); 210 + led_trigger_event(lp->recon_led_trig, LED_OFF); 211 + break; 212 + case ARCNET_LED_EVENT_TX: 213 + led_trigger_blink_oneshot(lp->tx_led_trig, 214 + &tx_delay, &tx_delay, 0); 215 + break; 216 + } 217 + } 218 + EXPORT_SYMBOL_GPL(arcnet_led_event); 219 + 220 + static void arcnet_led_release(struct device *gendev, void *res) 221 + { 222 + struct arcnet_local *lp = netdev_priv(to_net_dev(gendev)); 223 + 224 + led_trigger_unregister_simple(lp->tx_led_trig); 225 + led_trigger_unregister_simple(lp->recon_led_trig); 226 + } 227 + 228 + /* Register ARCNET LED triggers for a arcnet device 229 + * 230 + * This is normally called from a driver's probe function 231 + */ 232 + void devm_arcnet_led_init(struct net_device *netdev, int index, int subid) 233 + { 234 + struct arcnet_local *lp = netdev_priv(netdev); 235 + void *res; 236 + 237 + res = devres_alloc(arcnet_led_release, 0, GFP_KERNEL); 238 + if (!res) { 239 + netdev_err(netdev, "cannot register LED triggers\n"); 240 + return; 241 + } 242 + 243 + snprintf(lp->tx_led_trig_name, sizeof(lp->tx_led_trig_name), 244 + "arc%d-%d-tx", index, subid); 245 + snprintf(lp->recon_led_trig_name, sizeof(lp->recon_led_trig_name), 246 + "arc%d-%d-recon", index, subid); 247 + 248 + led_trigger_register_simple(lp->tx_led_trig_name, 249 + &lp->tx_led_trig); 250 + led_trigger_register_simple(lp->recon_led_trig_name, 251 + &lp->recon_led_trig); 252 + 253 + devres_add(&netdev->dev, res); 254 + } 255 + EXPORT_SYMBOL_GPL(devm_arcnet_led_init); 193 256 194 257 /* Unregister a protocol driver from the arc_proto_map. Protocol drivers 195 258 * are responsible for registering themselves, but the unregister routine ··· 492 425 493 426 netif_start_queue(dev); 494 427 428 + arcnet_led_event(dev, ARCNET_LED_EVENT_OPEN); 495 429 return 0; 496 430 497 431 out_module_put: ··· 506 438 { 507 439 struct arcnet_local *lp = netdev_priv(dev); 508 440 441 + arcnet_led_event(dev, ARCNET_LED_EVENT_STOP); 509 442 netif_stop_queue(dev); 510 443 511 444 /* flush TX and disable RX */ ··· 653 584 lp->hw.intmask(dev, lp->intmask); 654 585 arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", 655 586 __FILE__, __LINE__, __func__, lp->hw.status(dev)); 587 + 588 + arcnet_led_event(dev, ARCNET_LED_EVENT_TX); 656 589 657 590 spin_unlock_irqrestore(&lp->lock, flags); 658 591 return retval; /* no need to try again */ ··· 908 837 909 838 arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n", 910 839 status); 840 + arcnet_led_event(dev, ARCNET_LED_EVENT_RECON); 911 841 /* MYRECON bit is at bit 7 of diagstatus */ 912 842 if (diagstatus & 0x80) 913 843 arc_printk(D_RECON, dev, "Put out that recon myself\n");
+73
drivers/net/arcnet/com20020-pci.c
··· 41 41 #include <linux/pci.h> 42 42 #include <linux/list.h> 43 43 #include <linux/io.h> 44 + #include <linux/leds.h> 44 45 45 46 #include "arcdevice.h" 46 47 #include "com20020.h" ··· 62 61 module_param(clockp, int, 0); 63 62 module_param(clockm, int, 0); 64 63 MODULE_LICENSE("GPL"); 64 + 65 + static void led_tx_set(struct led_classdev *led_cdev, 66 + enum led_brightness value) 67 + { 68 + struct com20020_dev *card; 69 + struct com20020_priv *priv; 70 + struct com20020_pci_card_info *ci; 71 + 72 + card = container_of(led_cdev, struct com20020_dev, tx_led); 73 + 74 + priv = card->pci_priv; 75 + ci = priv->ci; 76 + 77 + outb(!!value, priv->misc + ci->leds[card->index].green); 78 + } 79 + 80 + static void led_recon_set(struct led_classdev *led_cdev, 81 + enum led_brightness value) 82 + { 83 + struct com20020_dev *card; 84 + struct com20020_priv *priv; 85 + struct com20020_pci_card_info *ci; 86 + 87 + card = container_of(led_cdev, struct com20020_dev, recon_led); 88 + 89 + priv = card->pci_priv; 90 + ci = priv->ci; 91 + 92 + outb(!!value, priv->misc + ci->leds[card->index].red); 93 + } 65 94 66 95 static void com20020pci_remove(struct pci_dev *pdev); 67 96 ··· 201 170 202 171 card->index = i; 203 172 card->pci_priv = priv; 173 + card->tx_led.brightness_set = led_tx_set; 174 + card->tx_led.default_trigger = devm_kasprintf(&pdev->dev, 175 + GFP_KERNEL, "arc%d-%d-tx", 176 + dev->dev_id, i); 177 + card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, 178 + "pci:green:tx:%d-%d", 179 + dev->dev_id, i); 180 + 181 + card->tx_led.dev = &dev->dev; 182 + card->recon_led.brightness_set = led_recon_set; 183 + card->recon_led.default_trigger = devm_kasprintf(&pdev->dev, 184 + GFP_KERNEL, "arc%d-%d-recon", 185 + dev->dev_id, i); 186 + card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, 187 + "pci:red:recon:%d-%d", 188 + dev->dev_id, i); 189 + card->recon_led.dev = &dev->dev; 204 190 card->dev = dev; 191 + 192 + ret = devm_led_classdev_register(&pdev->dev, &card->tx_led); 193 + if (ret) 194 + goto out_port; 195 + 196 + ret = devm_led_classdev_register(&pdev->dev, &card->recon_led); 197 + if (ret) 198 + goto out_port; 205 199 206 200 dev_set_drvdata(&dev->dev, card); 207 201 208 202 ret = com20020_found(dev, IRQF_SHARED); 209 203 if (ret) 210 204 goto out_port; 205 + 206 + devm_arcnet_led_init(dev, dev->dev_id, i); 211 207 212 208 list_add(&card->list, &priv->list_dev); 213 209 } ··· 319 261 .offset = 0x10, 320 262 .size = 0x04, 321 263 }, 264 + .leds = { 265 + { 266 + .green = 0x0, 267 + .red = 0x1, 268 + }, 269 + }, 322 270 .rotary = 0x0, 323 271 .flags = ARC_CAN_10MBIT, 324 272 }; ··· 347 283 .bar = 2, 348 284 .offset = 0x10, 349 285 .size = 0x04, 286 + }, 287 + .leds = { 288 + { 289 + .green = 0x0, 290 + .red = 0x1, 291 + }, { 292 + .green = 0x2, 293 + .red = 0x3, 294 + }, 350 295 }, 351 296 .rotary = 0x0, 352 297 .flags = ARC_CAN_10MBIT,
+10
drivers/net/arcnet/com20020.h
··· 26 26 */ 27 27 #ifndef __COM20020_H 28 28 #define __COM20020_H 29 + #include <linux/leds.h> 29 30 30 31 int com20020_check(struct net_device *dev); 31 32 int com20020_found(struct net_device *dev, int shared); ··· 36 35 #define ARCNET_TOTAL_SIZE 8 37 36 38 37 #define PLX_PCI_MAX_CARDS 2 38 + 39 + struct ledoffsets { 40 + int green; 41 + int red; 42 + }; 39 43 40 44 struct com20020_pci_channel_map { 41 45 u32 bar; ··· 55 49 struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS]; 56 50 struct com20020_pci_channel_map misc_map; 57 51 52 + struct ledoffsets leds[PLX_PCI_MAX_CARDS]; 58 53 int rotary; 59 54 60 55 unsigned int flags; ··· 70 63 struct com20020_dev { 71 64 struct list_head list; 72 65 struct net_device *dev; 66 + 67 + struct led_classdev tx_led; 68 + struct led_classdev recon_led; 73 69 74 70 struct com20020_priv *pci_priv; 75 71 int index;
+7
include/linux/leds.h
··· 283 283 static inline void led_trigger_unregister_simple(struct led_trigger *trigger) {} 284 284 static inline void led_trigger_event(struct led_trigger *trigger, 285 285 enum led_brightness event) {} 286 + static inline void led_trigger_blink(struct led_trigger *trigger, 287 + unsigned long *delay_on, 288 + unsigned long *delay_off) {} 289 + static inline void led_trigger_blink_oneshot(struct led_trigger *trigger, 290 + unsigned long *delay_on, 291 + unsigned long *delay_off, 292 + int invert) {} 286 293 static inline void led_trigger_set_default(struct led_classdev *led_cdev) {} 287 294 static inline void led_trigger_set(struct led_classdev *led_cdev, 288 295 struct led_trigger *trigger) {}