+#ifdef SLLIN_LED_TRIGGER
+static void sllin_led_event(struct net_device *netdev, enum sllin_led_event event)
+{
+ struct sllin *sl = netdev_priv(netdev);
+
+ switch (event) {
+ case SLLIN_LED_EVENT_OPEN:
+ led_trigger_event(sl->tx_led_trig, LED_FULL);
+ led_trigger_event(sl->rx_led_trig, LED_FULL);
+ led_trigger_event(sl->rxtx_led_trig, LED_FULL);
+ break;
+ case SLLIN_LED_EVENT_STOP:
+ led_trigger_event(sl->tx_led_trig, LED_OFF);
+ led_trigger_event(sl->rx_led_trig, LED_OFF);
+ led_trigger_event(sl->rxtx_led_trig, LED_OFF);
+ break;
+ case SLLIN_LED_EVENT_TX:
+ if (led_delay) {
+ led_trigger_blink_oneshot(sl->tx_led_trig,
+ &led_delay, &led_delay, 1);
+ led_trigger_blink_oneshot(sl->rxtx_led_trig,
+ &led_delay, &led_delay, 1);
+ }
+ break;
+ case SLLIN_LED_EVENT_RX:
+ if (led_delay) {
+ led_trigger_blink_oneshot(sl->rx_led_trig,
+ &led_delay, &led_delay, 1);
+ led_trigger_blink_oneshot(sl->rxtx_led_trig,
+ &led_delay, &led_delay, 1);
+ }
+ break;
+ }
+}
+
+static void sllin_led_release(struct device *gendev, void *res)
+{
+ struct sllin *sl = netdev_priv(to_net_dev(gendev));
+
+ led_trigger_unregister_simple(sl->tx_led_trig);
+ led_trigger_unregister_simple(sl->rx_led_trig);
+ led_trigger_unregister_simple(sl->rxtx_led_trig);
+}
+
+static void devm_sllin_led_init(struct net_device *netdev)
+{
+ struct sllin *sl = netdev_priv(netdev);
+ void *res;
+
+ res = devres_alloc(sllin_led_release, 0, GFP_KERNEL);
+ if (!res) {
+ netdev_err(netdev, "cannot register LED triggers\n");
+ return;
+ }
+
+ snprintf(sl->tx_led_trig_name, sizeof(sl->tx_led_trig_name),
+ "%s-tx", netdev->name);
+ snprintf(sl->rx_led_trig_name, sizeof(sl->rx_led_trig_name),
+ "%s-rx", netdev->name);
+ snprintf(sl->rxtx_led_trig_name, sizeof(sl->rxtx_led_trig_name),
+ "%s-rxtx", netdev->name);
+
+ led_trigger_register_simple(sl->tx_led_trig_name,
+ &sl->tx_led_trig);
+ led_trigger_register_simple(sl->rx_led_trig_name,
+ &sl->rx_led_trig);
+ led_trigger_register_simple(sl->rxtx_led_trig_name,
+ &sl->rxtx_led_trig);
+
+ devres_add(&netdev->dev, res);
+}
+
+static struct sllin *netdev_priv_safe(struct net_device *dev)
+{
+ int i;
+
+ if (sllin_devs == NULL)
+ return NULL;
+
+ for (i = 0; i < maxdev; ++i)
+ if (sllin_devs[i] == dev)
+ return netdev_priv(dev);
+
+ return NULL;
+}
+
+static int sllin_netdev_notifier_call(struct notifier_block *nb, unsigned long msg,
+ void *ptr)
+{
+ struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
+ struct sllin *sl = netdev_priv_safe(netdev);
+ char name[SLLIN_LED_NAME_SZ];
+
+ if (!sl)
+ return NOTIFY_DONE;
+
+ if (!sl->tx_led_trig || !sl->rx_led_trig || !sl->rxtx_led_trig)
+ return NOTIFY_DONE;
+
+ if (msg == NETDEV_CHANGENAME) {
+ snprintf(name, sizeof(name), "%s-tx", netdev->name);
+ led_trigger_rename_static(name, sl->tx_led_trig);
+
+ snprintf(name, sizeof(name), "%s-rx", netdev->name);
+ led_trigger_rename_static(name, sl->rx_led_trig);
+
+ snprintf(name, sizeof(name), "%s-rxtx", netdev->name);
+ led_trigger_rename_static(name, sl->rxtx_led_trig);
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block sllin_netdev_notifier __read_mostly = {
+ .notifier_call = sllin_netdev_notifier_call,
+};
+#endif /* SLLIN_LED_TRIGGER */
+