Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[linux-2.6-microblaze.git] / net / core / devlink.c
index 97e9a22..4c63c9a 100644 (file)
@@ -2791,6 +2791,9 @@ static int devlink_reload(struct devlink *devlink, struct net *dest_net,
 {
        int err;
 
+       if (!devlink->reload_enabled)
+               return -EOPNOTSUPP;
+
        err = devlink->ops->reload_down(devlink, !!dest_net, extack);
        if (err)
                return err;
@@ -2809,7 +2812,7 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
        struct net *dest_net = NULL;
        int err;
 
-       if (!devlink_reload_supported(devlink))
+       if (!devlink_reload_supported(devlink) || !devlink->reload_enabled)
                return -EOPNOTSUPP;
 
        err = devlink_resources_validate(devlink, NULL, info);
@@ -3003,6 +3006,11 @@ static const struct devlink_param devlink_param_generic[] = {
                .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME,
                .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE,
        },
+       {
+               .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
+               .name = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_NAME,
+               .type = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_TYPE,
+       },
 };
 
 static int devlink_param_generic_verify(const struct devlink_param *param)
@@ -4411,12 +4419,11 @@ int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
 }
 EXPORT_SYMBOL_GPL(devlink_fmsg_string_put);
 
-int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
-                           u16 value_len)
+static int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
+                                  u16 value_len)
 {
        return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY);
 }
-EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put);
 
 int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
                               bool value)
@@ -4524,19 +4531,26 @@ int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
 EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put);
 
 int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
-                                const void *value, u16 value_len)
+                                const void *value, u32 value_len)
 {
+       u32 data_size;
+       u32 offset;
        int err;
 
-       err = devlink_fmsg_pair_nest_start(fmsg, name);
+       err = devlink_fmsg_arr_pair_nest_start(fmsg, name);
        if (err)
                return err;
 
-       err = devlink_fmsg_binary_put(fmsg, value, value_len);
-       if (err)
-               return err;
+       for (offset = 0; offset < value_len; offset += data_size) {
+               data_size = value_len - offset;
+               if (data_size > DEVLINK_FMSG_MAX_SIZE)
+                       data_size = DEVLINK_FMSG_MAX_SIZE;
+               err = devlink_fmsg_binary_put(fmsg, value + offset, data_size);
+               if (err)
+                       return err;
+       }
 
-       err = devlink_fmsg_pair_nest_end(fmsg);
+       err = devlink_fmsg_arr_pair_nest_end(fmsg);
        if (err)
                return err;
 
@@ -4733,6 +4747,7 @@ struct devlink_health_reporter {
        bool auto_recover;
        u8 health_state;
        u64 dump_ts;
+       u64 dump_real_ts;
        u64 error_count;
        u64 recovery_count;
        u64 last_recovery_ts;
@@ -4909,6 +4924,7 @@ static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
                goto dump_err;
 
        reporter->dump_ts = jiffies;
+       reporter->dump_real_ts = ktime_get_real_ns();
 
        return 0;
 
@@ -5058,6 +5074,10 @@ devlink_nl_health_reporter_fill(struct sk_buff *msg,
                              jiffies_to_msecs(reporter->dump_ts),
                              DEVLINK_ATTR_PAD))
                goto reporter_nest_cancel;
+       if (reporter->dump_fmsg &&
+           nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS,
+                             reporter->dump_real_ts, DEVLINK_ATTR_PAD))
+               goto reporter_nest_cancel;
 
        nla_nest_end(msg, reporter_attr);
        genlmsg_end(msg, hdr);
@@ -6308,12 +6328,49 @@ EXPORT_SYMBOL_GPL(devlink_register);
 void devlink_unregister(struct devlink *devlink)
 {
        mutex_lock(&devlink_mutex);
+       WARN_ON(devlink_reload_supported(devlink) &&
+               devlink->reload_enabled);
        devlink_notify(devlink, DEVLINK_CMD_DEL);
        list_del(&devlink->list);
        mutex_unlock(&devlink_mutex);
 }
 EXPORT_SYMBOL_GPL(devlink_unregister);
 
+/**
+ *     devlink_reload_enable - Enable reload of devlink instance
+ *
+ *     @devlink: devlink
+ *
+ *     Should be called at end of device initialization
+ *     process when reload operation is supported.
+ */
+void devlink_reload_enable(struct devlink *devlink)
+{
+       mutex_lock(&devlink_mutex);
+       devlink->reload_enabled = true;
+       mutex_unlock(&devlink_mutex);
+}
+EXPORT_SYMBOL_GPL(devlink_reload_enable);
+
+/**
+ *     devlink_reload_disable - Disable reload of devlink instance
+ *
+ *     @devlink: devlink
+ *
+ *     Should be called at the beginning of device cleanup
+ *     process when reload operation is supported.
+ */
+void devlink_reload_disable(struct devlink *devlink)
+{
+       mutex_lock(&devlink_mutex);
+       /* Mutex is taken which ensures that no reload operation is in
+        * progress while setting up forbidded flag.
+        */
+       devlink->reload_enabled = false;
+       mutex_unlock(&devlink_mutex);
+}
+EXPORT_SYMBOL_GPL(devlink_reload_disable);
+
 /**
  *     devlink_free - Free devlink instance resources
  *
@@ -7602,6 +7659,21 @@ static const struct devlink_trap devlink_trap_generic[] = {
        DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
        DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
        DEVLINK_TRAP(TAIL_DROP, DROP),
+       DEVLINK_TRAP(NON_IP_PACKET, DROP),
+       DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP),
+       DEVLINK_TRAP(DIP_LB, DROP),
+       DEVLINK_TRAP(SIP_MC, DROP),
+       DEVLINK_TRAP(SIP_LB, DROP),
+       DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP),
+       DEVLINK_TRAP(IPV4_SIP_BC, DROP),
+       DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP),
+       DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP),
+       DEVLINK_TRAP(MTU_ERROR, EXCEPTION),
+       DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION),
+       DEVLINK_TRAP(RPF, EXCEPTION),
+       DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION),
+       DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION),
+       DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION),
 };
 
 #define DEVLINK_TRAP_GROUP(_id)                                                      \
@@ -8186,7 +8258,7 @@ static void __net_exit devlink_pernet_pre_exit(struct net *net)
                        if (WARN_ON(!devlink_reload_supported(devlink)))
                                continue;
                        err = devlink_reload(devlink, &init_net, NULL);
-                       if (err)
+                       if (err && err != -EOPNOTSUPP)
                                pr_warn("Failed to reload devlink instance into init_net\n");
                }
        }