static int __ipv6_dev_mc_inc(struct net_device *dev,
			     const struct in6_addr *addr, unsigned int mode)
{
	struct ifmcaddr6 *mc;
	struct inet6_dev *idev;

	ASSERT_RTNL();

	/* we need to take a reference on idev */
	idev = in6_dev_get(dev);

	if (!idev)
		return -EINVAL;

	if (idev->dead) {
		in6_dev_put(idev);
		return -ENODEV;
	}

	mutex_lock(&idev->mc_lock);
	for_each_mc_mclock(idev, mc) {
		if (ipv6_addr_equal(&mc->mca_addr, addr)) {
			mc->mca_users++;
			ip6_mc_add_src(idev, &mc->mca_addr, mode, 0, NULL, 0);
			mutex_unlock(&idev->mc_lock);
			in6_dev_put(idev);
			return 0;
		}
	}

	mc = mca_alloc(idev, addr, mode);
	if (!mc) {
		mutex_unlock(&idev->mc_lock);
		in6_dev_put(idev);
		return -ENOMEM;
	}

	rcu_assign_pointer(mc->next, idev->mc_list);
	rcu_assign_pointer(idev->mc_list, mc);

	mca_get(mc);

	mld_del_delrec(idev, mc);
	igmp6_group_added(mc);
	mutex_unlock(&idev->mc_lock);
	ma_put(mc);
	return 0;
}
static int __ipv6_dev_mc_inc(struct net_device *dev,
			     const struct in6_addr *addr, unsigned int mode)
{
	struct ifmcaddr6 *mc;
	struct inet6_dev *idev;

	ASSERT_RTNL();

	 
	idev = in6_dev_get(dev);

	if (!idev)
		return -EINVAL;

	if (idev->dead) {
		in6_dev_put(idev);
		return -ENODEV;
	}

	mutex_lock(&idev->mc_lock);
	for_each_mc_mclock(idev, mc) {
		if (ipv6_addr_equal(&mc->mca_addr, addr)) {
			mc->mca_users++;
			ip6_mc_add_src(idev, &mc->mca_addr, mode, 0, NULL, 0);
			mutex_unlock(&idev->mc_lock);
			in6_dev_put(idev);
			return 0;
		}
	}

	mc = mca_alloc(idev, addr, mode);
	if (!mc) {
		mutex_unlock(&idev->mc_lock);
		in6_dev_put(idev);
		return -ENOMEM;
	}

	rcu_assign_pointer(mc->next, idev->mc_list);
	rcu_assign_pointer(idev->mc_list, mc);

	mca_get(mc);

	mld_del_delrec(idev, mc);
	igmp6_group_added(mc);
	mutex_unlock(&idev->mc_lock);
	ma_put(mc);
	return 0;
}