+static int
+wprobe_set_config(struct sk_buff *skb, struct genl_info *info)
+{
+ struct wprobe_iface *dev;
+ unsigned long flags;
+ int err = -ENOENT;
+ u32 scale_min, scale_max;
+ u32 scale_m, scale_d;
+
+ rcu_read_lock();
+ dev = wprobe_get_dev(info->attrs[WPROBE_ATTR_INTERFACE]);
+ if (!dev)
+ goto done_unlocked;
+
+ err = -EINVAL;
+ spin_lock_irqsave(&dev->lock, flags);
+ if (info->attrs[WPROBE_ATTR_MAC]) {
+ /* not supported yet */
+ goto done;
+ }
+
+ if (info->attrs[WPROBE_ATTR_SAMPLES_MIN] ||
+ info->attrs[WPROBE_ATTR_SAMPLES_MAX]) {
+ if (info->attrs[WPROBE_ATTR_SAMPLES_MIN])
+ scale_min = nla_get_u32(info->attrs[WPROBE_ATTR_SAMPLES_MIN]);
+ else
+ scale_min = dev->scale_min;
+
+ if (info->attrs[WPROBE_ATTR_SAMPLES_MAX])
+ scale_max = nla_get_u32(info->attrs[WPROBE_ATTR_SAMPLES_MAX]);
+ else
+ scale_max = dev->scale_max;
+
+ if ((!scale_min && !scale_max) ||
+ (scale_min && scale_max && (scale_min < scale_max))) {
+ dev->scale_min = scale_min;
+ dev->scale_max = scale_max;
+ } else {
+ goto done;
+ }
+ }
+
+ if (info->attrs[WPROBE_ATTR_SAMPLES_SCALE_M] &&
+ info->attrs[WPROBE_ATTR_SAMPLES_SCALE_D]) {
+
+ scale_m = nla_get_u32(info->attrs[WPROBE_ATTR_SAMPLES_SCALE_M]);
+ scale_d = nla_get_u32(info->attrs[WPROBE_ATTR_SAMPLES_SCALE_D]);
+
+ if (!scale_d || (scale_m > scale_d))
+ goto done;
+
+ dev->scale_m = scale_m;
+ dev->scale_d = scale_d;
+ }
+
+ err = 0;
+ if (info->attrs[WPROBE_ATTR_INTERVAL]) {
+ /* change of measurement interval requested */
+ err = wprobe_update_auto_measurement(dev,
+ (u32) nla_get_u64(info->attrs[WPROBE_ATTR_INTERVAL]));
+ }
+
+done:
+ spin_unlock_irqrestore(&dev->lock, flags);
+done_unlocked:
+ rcu_read_unlock();
+ return err;
+}
+