Merge "[qca-nss-ecm] Improve NSS / HyFi integration"
diff --git a/Makefile b/Makefile
index a0e5d4a..f017c40 100755
--- a/Makefile
+++ b/Makefile
@@ -109,13 +109,10 @@
 # Define ECM_MULTICAST_ENABLE=y in order to enable support for ECM Multicast
 # #############################################################################
 ifeq ($(ECM_FRONT_END_NSS_ENABLE), y)
-ifneq ($(findstring 3.4, $(KERNELVERSION)),)
-ECM_MULTICAST_ENABLE=y
-endif
-endif
 ecm-$(ECM_MULTICAST_ENABLE) += frontends/nss/ecm_nss_multicast_ipv4.o
 ecm-$(ECM_MULTICAST_ENABLE) += frontends/nss/ecm_nss_multicast_ipv6.o
 ccflags-$(ECM_MULTICAST_ENABLE) += -DECM_MULTICAST_ENABLE
+endif
 
 # #############################################################################
 # Define ECM_INTERFACE_VLAN_ENABLE=y in order to enable support for VLAN
diff --git a/ecm_interface.c b/ecm_interface.c
index 9ff2b9e..c94bb6b 100644
--- a/ecm_interface.c
+++ b/ecm_interface.c
@@ -2381,7 +2381,8 @@
 	if (in_dev && !mfc_update) {
 		if (ecm_front_end_is_bridge_port(in_dev)) {
 			src_dev_is_bridge = true;
-			br_dev_src = in_dev->master;
+			br_dev_src = ecm_interface_get_and_hold_dev_master(in_dev);
+			DEBUG_ASSERT(br_dev_src, "Expected a master\n");
 
 			/*
 	 		 * The source net_dev found as bridge slave. In case of routed interface
@@ -2431,8 +2432,9 @@
 				 */
 				return 0;
 			}
+
 			dest_dev = br_dev_src;
-			dev_hold(dest_dev);
+
 		}
 
 		dest_dev_type = dest_dev->type;
diff --git a/frontends/nss/ecm_nss_multicast_ipv4.c b/frontends/nss/ecm_nss_multicast_ipv4.c
index 1b87bb1..20ab413 100644
--- a/frontends/nss/ecm_nss_multicast_ipv4.c
+++ b/frontends/nss/ecm_nss_multicast_ipv4.c
@@ -2166,6 +2166,7 @@
 	int dest_port;
 	int src_port_nat = 0;
 	struct net_device *in_dev_nat = NULL;
+	struct net_device *out_dev_master = NULL;
 	struct ecm_db_multicast_tuple_instance *tuple_instance;
 	struct ecm_db_connection_instance *ci;
 	ip_addr_t match_addr;
@@ -2268,14 +2269,18 @@
 			is_routed = true;
 			br_dev_found_in_mfc = ecm_interface_multicast_check_for_br_dev(dst_dev, if_cnt);
 		} else {
+			out_dev_master =  ecm_interface_get_and_hold_dev_master(out_dev);
+			DEBUG_ASSERT(out_dev_master, "Expected a master\n");
+
+
 			/*
 			 * Packet flow is pure bridge. Try to query the snooper for the destination
 			 * interface list
 			 */
-			if_cnt = mc_bridge_ipv4_get_if(out_dev->master, ip_src, ip_grp, ECM_DB_MULTICAST_IF_MAX, dst_dev);
+			if_cnt = mc_bridge_ipv4_get_if(out_dev_master, ip_src, ip_grp, ECM_DB_MULTICAST_IF_MAX, dst_dev);
 			if (if_cnt <= 0) {
 				DEBUG_WARN("Not found a valid MCS if count %d\n", if_cnt);
-				return NF_ACCEPT;
+				goto done;
 			}
 
 			/*
@@ -2287,7 +2292,7 @@
 			if_cnt = ecm_interface_multicast_check_for_src_ifindex(dst_dev, if_cnt, in_dev->ifindex);
 			if (if_cnt <= 0) {
 				DEBUG_WARN("Not found a valid MCS if count %d\n", if_cnt);
-				return NF_ACCEPT;
+				goto done;
 			}
 		}
 	}
@@ -2298,7 +2303,7 @@
 	if (!is_routed) {
 		if (iph->ttl < 2) {
 			DEBUG_TRACE("%p: Ignoring, Multicast IPv4 Header has TTL one\n", skb);
-			return NF_ACCEPT;
+			goto done;
 		}
 	}
 
@@ -2315,7 +2320,7 @@
 		 */
 		in_dev_nat = ecm_interface_dev_find_by_addr(ip_src_addr_nat, &from_local_addr);
 		if (!in_dev_nat) {
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2335,7 +2340,7 @@
 		 * list for a NAT flow, which should not happen.
 		 */
 		if (!nat_if_found) {
-			return NF_ACCEPT;
+			goto done;
 		}
 	}
 
@@ -2385,7 +2390,7 @@
 			/*
 			 * As we are terminating we just allow the packet to pass - it's no longer our concern
 			 */
-			return NF_ACCEPT;
+			goto done;
 		}
 		spin_unlock_bh(&ecm_nss_ipv4_lock);
 
@@ -2395,7 +2400,7 @@
 		nci = ecm_db_connection_alloc();
 		if (!nci) {
 			DEBUG_WARN("Failed to allocate connection\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2405,7 +2410,7 @@
 		if (!feci) {
 			ecm_db_connection_deref(nci);
 			DEBUG_WARN("Failed to allocate front end\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2415,7 +2420,7 @@
 		if (!tuple_instance) {
 			ecm_db_connection_deref(nci);
 			DEBUG_WARN("Failed to allocate tuple instance\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2434,7 +2439,7 @@
 			ecm_db_connection_deref(nci);
 			ecm_db_multicast_tuple_instance_deref(tuple_instance);
 			DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 		ecm_db_connection_from_interfaces_reset(nci, from_list, from_list_first);
 
@@ -2446,7 +2451,7 @@
 			feci->deref(feci);
 			ecm_db_connection_deref(nci);
 			ecm_db_multicast_tuple_instance_deref(tuple_instance);
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		DEBUG_TRACE("%p: Create source mapping\n", nci);
@@ -2457,7 +2462,7 @@
 			feci->deref(feci);
 			ecm_db_connection_deref(nci);
 			ecm_db_multicast_tuple_instance_deref(tuple_instance);
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN);
@@ -2468,7 +2473,7 @@
 			feci->deref(feci);
 			ecm_db_connection_deref(nci);
 			ecm_db_multicast_tuple_instance_deref(tuple_instance);
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN);
@@ -2481,7 +2486,7 @@
 			ecm_db_connection_deref(nci);
 			ecm_db_multicast_tuple_instance_deref(tuple_instance);
 			kfree(to_list);
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2494,7 +2499,7 @@
 		}
 
 		interface_idx_cnt = ecm_nss_multicast_connection_to_interface_heirarchy_construct(feci, to_list, ip_src_addr, ip_dest_addr, in_dev,
-												  out_dev->master, if_cnt, dst_dev, to_list_first,
+												  out_dev_master, if_cnt, dst_dev, to_list_first,
 												  src_node_addr, is_routed, layer4hdr, skb);
 		if (interface_idx_cnt == 0) {
 			ecm_db_node_deref(src_ni);
@@ -2505,7 +2510,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("%p: Failed to obtain mutlicast 'to' heirarchy list\n", nci);
-			return NF_ACCEPT;
+			goto done;
 		}
 		ret = ecm_db_multicast_connection_to_interfaces_reset(nci, to_list, to_list_first);
 		if (ret < 0) {
@@ -2524,7 +2529,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("%p: Failed to obtain mutlicast 'to' heirarchy list\n", nci);
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		DEBUG_TRACE("%p: Create destination node\n", nci);
@@ -2550,7 +2555,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("Failed to establish destination node\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		DEBUG_TRACE("%p: Create source mapping\n", nci);
@@ -2572,7 +2577,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("Failed to establish dst mapping\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		DEBUG_TRACE("%p: Create the 'from NAT' interface heirarchy list\n", nci);
@@ -2595,7 +2600,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("Failed to obtain 'from NAT' heirarchy list\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 		ecm_db_connection_from_nat_interfaces_reset(nci, from_nat_list, from_nat_list_first);
 
@@ -2619,7 +2624,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("Failed to obtain 'from NAT' node\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		DEBUG_TRACE("%p: Create from NAT mapping\n", nci);
@@ -2644,7 +2649,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("Failed to establish from nat mapping\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2671,7 +2676,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("Failed to allocate default classifier\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 		ecm_db_connection_classifier_assign(nci, (struct ecm_classifier_instance *)dci);
 
@@ -2704,7 +2709,7 @@
 				kfree(to_list);
 				kfree(to_list_first);
 				DEBUG_WARN("Failed to allocate classifiers assignments\n");
-				return NF_ACCEPT;
+				goto done;
 			}
 		}
 
@@ -2799,14 +2804,14 @@
 			to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN);
 			if (!to_list) {
 				ecm_db_connection_deref(ci);
-				return NF_ACCEPT;
+				goto done;
 			}
 
 			to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN);
 			if (!to_list_first) {
 				ecm_db_connection_deref(ci);
 				kfree(to_list);
-				return NF_ACCEPT;
+				goto done;
 			}
 
 			/*
@@ -2819,7 +2824,7 @@
 
 			feci = ecm_db_connection_front_end_get_and_ref(ci);
 			interface_idx_cnt = ecm_nss_multicast_connection_to_interface_heirarchy_construct(feci, to_list, ip_src_addr, ip_dest_addr, in_dev,
-													  out_dev->master, if_cnt, dst_dev, to_list_first,
+													  out_dev_master, if_cnt, dst_dev, to_list_first,
 													  src_node_addr, is_routed, (__be16 *)&udp_hdr, skb);
 			feci->deref(feci);
 			if (interface_idx_cnt == 0) {
@@ -2827,7 +2832,7 @@
 				ecm_db_connection_deref(ci);
 				kfree(to_list);
 				kfree(to_list_first);
-				return NF_ACCEPT;
+				goto done;
 			}
 
 			ret = ecm_db_multicast_connection_to_interfaces_reset(ci, to_list, to_list_first);
@@ -2850,7 +2855,7 @@
 			 */
 			if (ret < 0) {
 				ecm_db_connection_deref(ci);
-				return NF_ACCEPT;
+				goto done;
 			}
 		}
 	}
@@ -2860,7 +2865,7 @@
 	 */
 	if (!ecm_db_connection_defunct_timer_touch(ci)) {
 		ecm_db_connection_deref(ci);
-		return NF_ACCEPT;
+		goto done;
 	}
 
 	/*
@@ -3013,7 +3018,7 @@
 		DEBUG_TRACE("%p: drop: %p\n", ci, skb);
 		ecm_db_connection_data_totals_update_dropped(ci, (sender == ECM_TRACKER_SENDER_TYPE_SRC)? true : false, skb->len, 1);
 		ecm_db_connection_deref(ci);
-		return NF_ACCEPT;
+		goto done;
 	}
 	ecm_db_multicast_connection_data_totals_update(ci, false, skb->len, 1);
 
@@ -3025,11 +3030,13 @@
 		feci = ecm_db_connection_front_end_get_and_ref(ci);
 		ecm_nss_multicast_ipv4_connection_accelerate(feci, &prevalent_pr);
 		feci->deref(feci);
-	} else {
-		goto done;
 	}
-done:
 	ecm_db_connection_deref(ci);
+
+done:
+	if (out_dev_master) {
+		dev_put(out_dev_master);
+	}
 	return NF_ACCEPT;
 }
 
diff --git a/frontends/nss/ecm_nss_multicast_ipv6.c b/frontends/nss/ecm_nss_multicast_ipv6.c
index a40d0a1..42ddefd 100644
--- a/frontends/nss/ecm_nss_multicast_ipv6.c
+++ b/frontends/nss/ecm_nss_multicast_ipv6.c
@@ -2125,6 +2125,7 @@
 	bool br_dev_found_in_mfc = false;
 	int protocol = (int)orig_tuple->dst.protonum;
 	__be16 *layer4hdr = NULL;
+	struct net_device *out_dev_master = NULL;
 
 	if (protocol != IPPROTO_UDP) {
 		DEBUG_WARN("Invalid Protocol %d in skb %p\n", protocol, skb);
@@ -2207,15 +2208,17 @@
 			is_routed = true;
 			br_dev_found_in_mfc = ecm_interface_multicast_check_for_br_dev(mc_dest_if, mc_if_cnt);
 		} else {
+			out_dev_master =  ecm_interface_get_and_hold_dev_master(out_dev);
+			DEBUG_ASSERT(out_dev_master, "Expected a master\n");
 
 			/*
 			 * Packet flow is pure bridge. Try to query the snooper for the destination
 			 * interface list
 			 */
-			mc_if_cnt = mc_bridge_ipv6_get_if(out_dev->master, &origin6, &group6, ECM_DB_MULTICAST_IF_MAX, mc_dest_if);
+			mc_if_cnt = mc_bridge_ipv6_get_if(out_dev_master, &origin6, &group6, ECM_DB_MULTICAST_IF_MAX, mc_dest_if);
 			if (mc_if_cnt <= 0) {
 				DEBUG_WARN("Not found a valid MCS if count %d\n", mc_if_cnt);
-				return NF_ACCEPT;
+				goto done;
 			}
 
 			/*
@@ -2227,7 +2230,7 @@
 			mc_if_cnt = ecm_interface_multicast_check_for_src_ifindex(mc_dest_if, mc_if_cnt, in_dev->ifindex);
 			if (mc_if_cnt <= 0) {
 				DEBUG_WARN("Not found a valid MCS if count %d\n", mc_if_cnt);
-				return NF_ACCEPT;
+				goto done;
 			}
 		}
 	}
@@ -2238,7 +2241,7 @@
 	if (!is_routed) {
 		if (iph->ttl < 2) {
 			DEBUG_TRACE("%p: Ignoring, Multicast IPv6 Header has Hop Limit one\n", skb);
-			return NF_ACCEPT;
+			goto done;
 		}
 	}
 
@@ -2288,7 +2291,7 @@
 			/*
 			 * As we are terminating we just allow the packet to pass - it's no longer our concern
 			 */
-			return NF_ACCEPT;
+			goto done;
 		}
 		spin_unlock_bh(&ecm_nss_ipv6_lock);
 
@@ -2298,7 +2301,7 @@
 		nci = ecm_db_connection_alloc();
 		if (!nci) {
 			DEBUG_WARN("Failed to allocate connection\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2308,7 +2311,7 @@
 		if (!feci) {
 			ecm_db_connection_deref(nci);
 			DEBUG_WARN("Failed to allocate front end\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2318,7 +2321,7 @@
 		if (!tuple_instance) {
 			ecm_db_connection_deref(nci);
 			DEBUG_WARN("Failed to allocate tuple instance\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 		/*
 		 * Create Destination MAC address using IP multicast destination address
@@ -2338,7 +2341,7 @@
 			ecm_db_connection_deref(nci);
 			ecm_db_multicast_tuple_instance_deref(tuple_instance);
 			DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 		ecm_db_connection_from_interfaces_reset(nci, from_list, from_list_first);
 
@@ -2350,7 +2353,7 @@
 			ecm_db_connection_deref(nci);
 			ecm_db_multicast_tuple_instance_deref(tuple_instance);
 			DEBUG_WARN("Failed to establish source node\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		DEBUG_TRACE("%p: Create source mapping\n", nci);
@@ -2361,7 +2364,7 @@
 			ecm_db_connection_deref(nci);
 			ecm_db_multicast_tuple_instance_deref(tuple_instance);
 			DEBUG_WARN("Failed to establish src mapping\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		DEBUG_TRACE("%p: Create the 'to' interface heirarchy list\n", nci);
@@ -2373,7 +2376,7 @@
 			feci->deref(feci);
 			ecm_db_connection_deref(nci);
 			ecm_db_multicast_tuple_instance_deref(tuple_instance);
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN);
@@ -2385,7 +2388,7 @@
 			ecm_db_connection_deref(nci);
 			ecm_db_multicast_tuple_instance_deref(tuple_instance);
 			kfree(to_list);
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2397,7 +2400,7 @@
 			*to_first = ECM_DB_IFACE_HEIRARCHY_MAX;
 		}
 
-		interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev->master, ip_src_addr,
+		interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev_master, ip_src_addr,
 										      ip_dest_addr, mc_if_cnt, mc_dest_if, to_list_first, src_node_addr,  is_routed, skb);
 		if (interface_idx_cnt == 0) {
 			DEBUG_WARN("Failed to obtain 'to' heirarchy list\n");
@@ -2407,7 +2410,7 @@
 			ecm_db_connection_deref(nci);
 			kfree(to_list);
 			kfree(to_list_first);
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		ret = ecm_db_multicast_connection_to_interfaces_reset(nci, to_list, to_list_first);
@@ -2427,7 +2430,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("Failed to obtain 'to' heirarchy list\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2458,7 +2461,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("Failed to establish dest node\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		DEBUG_TRACE("%p: Create dest mapping\n", nci);
@@ -2479,7 +2482,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("Failed to establish dest mapping\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 
 		/*
@@ -2503,7 +2506,7 @@
 			kfree(to_list);
 			kfree(to_list_first);
 			DEBUG_WARN("Failed to allocate default classifier\n");
-			return NF_ACCEPT;
+			goto done;
 		}
 		ecm_db_connection_classifier_assign(nci, (struct ecm_classifier_instance *)dci);
 
@@ -2533,7 +2536,7 @@
 				kfree(to_list);
 				kfree(to_list_first);
 				DEBUG_WARN("Failed to allocate classifiers assignments\n");
-				return NF_ACCEPT;
+				goto done;
 			}
 		}
 
@@ -2634,14 +2637,14 @@
 			to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN);
 			if (!to_list) {
 				ecm_db_connection_deref(ci);
-				return NF_ACCEPT;
+				goto done;
 			}
 
 			to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN);
 			if (!to_list_first) {
 				ecm_db_connection_deref(ci);
 				kfree(to_list);
-				return NF_ACCEPT;
+				goto done;
 			}
 
 			for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) {
@@ -2650,7 +2653,7 @@
 			}
 
 			feci = ecm_db_connection_front_end_get_and_ref(ci);
-			interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev->master,\
+			interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev_master,\
 												   ip_src_addr, ip_dest_addr, mc_if_cnt,\
 												   mc_dest_if, to_list_first, src_node_addr,
 												   is_routed, skb);
@@ -2660,7 +2663,7 @@
 				ecm_db_connection_deref(ci);
 				kfree(to_list);
 				kfree(to_list_first);
-				return NF_ACCEPT;
+				goto done;
 			}
 
 			ret = ecm_db_multicast_connection_to_interfaces_reset(ci, to_list, to_list_first);
@@ -2684,7 +2687,7 @@
 			 */
 			if (ret < 0) {
 				ecm_db_connection_deref(ci);
-				return NF_ACCEPT;
+				goto done;
 			}
 		}
 	}
@@ -2694,7 +2697,7 @@
 	 */
 	if (!ecm_db_connection_defunct_timer_touch(ci)) {
 		ecm_db_connection_deref(ci);
-		return NF_ACCEPT;
+		goto done;
 	}
 
 	/*
@@ -2847,7 +2850,7 @@
 		DEBUG_TRACE("%p: drop: %p\n", ci, skb);
 		ecm_db_connection_data_totals_update_dropped(ci, (sender == ECM_TRACKER_SENDER_TYPE_SRC)? true : false, skb->len, 1);
 		ecm_db_connection_deref(ci);
-		return NF_ACCEPT;
+		goto done;
 	}
 	ecm_db_connection_data_totals_update(ci, (sender == ECM_TRACKER_SENDER_TYPE_SRC)? true : false, skb->len, 1);
 
@@ -2867,11 +2870,13 @@
 		feci = ecm_db_connection_front_end_get_and_ref(ci);
 		ecm_nss_multicast_ipv6_connection_accelerate(feci, &prevalent_pr);
 		feci->deref(feci);
-	} else {
-		goto done;
 	}
-done:
 	ecm_db_connection_deref(ci);
+
+done:
+	if (out_dev_master) {
+		dev_put(out_dev_master);
+	}
 	return NF_ACCEPT;
 }