static ssize_t led_device_name_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_cdev->trigger_data; if (size < 0 || size >= IFNAMSIZ) return -EINVAL; write_lock(&trigger_data->lock); strcpy(trigger_data->device_name, buf); if (size > 0 && trigger_data->device_name[size-1] == '\n') trigger_data->device_name[size-1] = 0; if (trigger_data->device_name[0] != 0) { /* check for existing device to update from */ trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name); if (trigger_data->net_dev != NULL) trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0; set_baseline_state(trigger_data); /* updates LEDs, may start timers */ } write_unlock(&trigger_data->lock); return size; }
static ssize_t led_interval_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_cdev->trigger_data; int ret = -EINVAL; char *after; unsigned long value = simple_strtoul(buf, &after, 10); size_t count = after - buf; if (isspace(*after)) count++; /* impose some basic bounds on the timer interval */ if (count == size && value >= 5 && value <= 10000) { spin_lock_bh(&trigger_data->lock); del_timer_sync(&trigger_data->timer); trigger_data->interval = msecs_to_jiffies(value); set_baseline_state(trigger_data); /* resets timer */ spin_unlock_bh(&trigger_data->lock); ret = count; } return ret; }
static ssize_t led_device_name_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_cdev->trigger_data; if (size >= IFNAMSIZ) return -EINVAL; cancel_delayed_work_sync(&trigger_data->work); spin_lock_bh(&trigger_data->lock); strcpy(trigger_data->device_name, buf); if (size > 0 && trigger_data->device_name[size-1] == '\n') trigger_data->device_name[size-1] = 0; trigger_data->link_up = 0; trigger_data->last_activity = 0; if (trigger_data->device_name[0] != 0) { /* check for existing device to update from */ trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name); if (trigger_data->net_dev != NULL) trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0; } set_baseline_state(trigger_data); spin_unlock_bh(&trigger_data->lock); return size; }
static ssize_t led_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_netdev_data *trigger_data = led_cdev->trigger_data; char copybuf[128]; int new_mode = -1; char *p, *token; /* take a copy since we don't want to trash the inbound buffer when using strsep */ strncpy(copybuf, buf, sizeof(copybuf)); copybuf[sizeof(copybuf) - 1] = 0; p = copybuf; while ((token = strsep(&p, " \t\n")) != NULL) { if (!*token) continue; if (new_mode == -1) new_mode = 0; if (!strcmp(token, "none")) new_mode = 0; else if (!strcmp(token, "tx")) new_mode |= MODE_TX; else if (!strcmp(token, "rx")) new_mode |= MODE_RX; else if (!strcmp(token, "link")) new_mode |= MODE_LINK; else return -EINVAL; } if (new_mode == -1) return -EINVAL; spin_lock_bh(&trigger_data->lock); del_timer_sync(&trigger_data->timer); trigger_data->mode = new_mode; set_baseline_state(trigger_data); spin_unlock_bh(&trigger_data->lock); return size; }
static int netdev_trig_notify(struct notifier_block *nb, unsigned long evt, void *dv) { struct net_device *dev = netdev_notifier_info_to_dev((struct netdev_notifier_info *) dv); struct led_netdev_data *trigger_data = container_of(nb, struct led_netdev_data, notifier); if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER && evt != NETDEV_CHANGENAME) return NOTIFY_DONE; spin_lock_bh(&trigger_data->lock); if (strcmp(dev->name, trigger_data->device_name)) goto done; del_timer_sync(&trigger_data->timer); if (evt == NETDEV_REGISTER || evt == NETDEV_CHANGENAME) { if (trigger_data->net_dev != NULL) dev_put(trigger_data->net_dev); dev_hold(dev); trigger_data->net_dev = dev; trigger_data->link_up = 0; goto done; } if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) { dev_put(trigger_data->net_dev); trigger_data->net_dev = NULL; goto done; } /* UP / DOWN / CHANGE */ trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev)); set_baseline_state(trigger_data); done: spin_unlock_bh(&trigger_data->lock); return NOTIFY_DONE; }