+#ifdef CONFIG_IPV6_MODULE
+
+struct nx_ipv6_mod vc_net_ipv6 = {
+ .dev_in_nx_info6 = NULL,
+ .owner = NULL
+};
+
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+static atomic_t nx_ipv6mod_lockct = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(nx_ipv6mod_lock);
+
+/* The strategy is: modifications of vc_net_ipv6 are short, do not
+ sleep and veeery rare, but read access should be free of any exclusive
+ locks. (copied from socket.c)
+ This should prevent any possible issues with module unloading!
+ */
+
+static void nx_ipv6mod_write_lock(void)
+{
+ spin_lock(&nx_ipv6mod_lock);
+ while (atomic_read(&nx_ipv6mod_lockct) != 0) {
+ spin_unlock(&nx_ipv6mod_lock);
+
+ yield();
+
+ spin_lock(&nx_ipv6mod_lock);
+ }
+}
+
+static __inline__ void nx_ipv6mod_write_unlock(void)
+{
+ spin_unlock(&nx_ipv6mod_lock);
+}
+
+static __inline__ void nx_ipv6mod_read_lock(void)
+{
+ atomic_inc(&nx_ipv6mod_lockct);
+ spin_unlock_wait(&nx_ipv6mod_lock);
+}
+
+static __inline__ void nx_ipv6mod_read_unlock(void)
+{
+ atomic_dec(&nx_ipv6mod_lockct);
+}
+
+#else
+#define nx_ipv6mod_write_lock() do { } while(0)
+#define nx_ipv6mod_write_unlock() do { } while(0)
+#define nx_ipv6mod_read_lock() do { } while(0)
+#define nx_ipv6mod_read_unlock() do { } while(0)
+#endif
+
+void vc_net_register_ipv6(struct nx_ipv6_mod *modv6) {
+ nx_ipv6mod_write_lock();
+ memcpy(&vc_net_ipv6, modv6, sizeof(struct nx_ipv6_mod));
+ nx_ipv6mod_write_unlock();
+}
+
+void vc_net_unregister_ipv6() {
+ nx_ipv6mod_write_lock();
+ memset(&vc_net_ipv6, 0, sizeof(struct nx_ipv6_mod));
+ nx_ipv6mod_write_unlock();
+}
+
+inline int dev_in_nx_info6(struct net_device *dev, struct nx_info *nxi) {
+ nx_ipv6mod_read_lock();
+ if (try_module_get(vc_net_ipv6.owner)) {
+ if (vc_net_ipv6.dev_in_nx_info6)
+ return vc_net_ipv6.dev_in_nx_info6(dev, nxi);
+ else
+ return 0;
+ module_put(vc_net_ipv6.owner);
+ } else
+ return 0;
+ nx_ipv6mod_read_unlock();
+}
+#endif
+