Currently, struct ifmcaddr6 doesn't use list API so that code shape is
a little bit different from others.
So it converts ifmcaddr6 to use list API so it would improve readability.

Signed-off-by: Taehee Yoo <ap420...@gmail.com>
---
 drivers/s390/net/qeth_l3_main.c |   2 +-
 include/net/if_inet6.h          |   9 +-
 net/batman-adv/multicast.c      |   2 +-
 net/ipv6/addrconf.c             |   7 +-
 net/ipv6/addrconf_core.c        |   3 +-
 net/ipv6/mcast.c                | 999 ++++++++++++++++----------------
 6 files changed, 523 insertions(+), 499 deletions(-)

diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index dd441eaec66e..e49abdeff69c 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1099,7 +1099,7 @@ static int qeth_l3_add_mcast_rtnl(struct net_device *dev, 
int vid, void *arg)
        tmp.is_multicast = 1;
 
        read_lock_bh(&in6_dev->lock);
-       for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
+       list_for_each_entry(im6, in6_dev->mc_list, list) {
                tmp.u.a6.addr = im6->mca_addr;
 
                ipm = qeth_l3_find_addr_by_ip(card, &tmp);
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 8bf5906073bc..1262ccd5221e 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -114,7 +114,7 @@ struct ip6_sf_list {
 struct ifmcaddr6 {
        struct in6_addr         mca_addr;
        struct inet6_dev        *idev;
-       struct ifmcaddr6        *next;
+       struct list_head        list;
        struct ip6_sf_list      *mca_sources;
        struct ip6_sf_list      *mca_tomb;
        unsigned int            mca_sfmode;
@@ -164,10 +164,9 @@ struct inet6_dev {
        struct net_device       *dev;
 
        struct list_head        addr_list;
-
-       struct ifmcaddr6        *mc_list;
-       struct ifmcaddr6        *mc_tomb;
-       spinlock_t              mc_lock;
+       struct list_head        mc_list;
+       struct list_head        mc_tomb_list;
+       spinlock_t              mc_tomb_lock;
 
        unsigned char           mc_qrv;         /* Query Robustness Variable */
        unsigned char           mc_gq_running;
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index 854e5ff28a3f..1a9ad5a9257b 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -455,7 +455,7 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
        }
 
        read_lock_bh(&in6_dev->lock);
-       for (pmc6 = in6_dev->mc_list; pmc6; pmc6 = pmc6->next) {
+       list_for_each_entry(pmc6, &in6_dev->mc_list, list) {
                if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) <
                    IPV6_ADDR_SCOPE_LINKLOCAL)
                        continue;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f2337fb756ac..e9fe0eee5768 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -5110,13 +5110,14 @@ static int in6_dump_addrs(struct inet6_dev *idev, 
struct sk_buff *skb,
                fillargs->event = RTM_GETMULTICAST;
 
                /* multicast address */
-               for (ifmca = idev->mc_list; ifmca;
-                    ifmca = ifmca->next, ip_idx++) {
+               list_for_each_entry(ifmca, &idev->mc_list, list) {
                        if (ip_idx < s_ip_idx)
-                               continue;
+                               goto next2;
                        err = inet6_fill_ifmcaddr(skb, ifmca, fillargs);
                        if (err < 0)
                                break;
+next2:
+                       ip_idx++;
                }
                break;
        case ANYCAST_ADDR:
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index c70c192bc91b..b55f85dcfd74 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -250,7 +250,8 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
        struct net_device *dev = idev->dev;
 
        WARN_ON(!list_empty(&idev->addr_list));
-       WARN_ON(idev->mc_list);
+       WARN_ON(!list_empty(&idev->mc_list));
+       WARN_ON(!list_empty(&idev->mc_tomb_list));
        WARN_ON(timer_pending(&idev->rs_timer));
 
 #ifdef NET_REFCNT_DEBUG
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 6c8604390266..508c007df84f 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -69,24 +69,19 @@ static int __mld2_query_bugs[] __attribute__((__unused__)) 
= {
 
 static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
 
-static void igmp6_join_group(struct ifmcaddr6 *ma);
-static void igmp6_leave_group(struct ifmcaddr6 *ma);
+static void igmp6_join_group(struct ifmcaddr6 *mc);
+static void igmp6_leave_group(struct ifmcaddr6 *mc);
 static void igmp6_timer_handler(struct timer_list *t);
 
-static void mld_gq_timer_expire(struct timer_list *t);
-static void mld_ifc_timer_expire(struct timer_list *t);
 static void mld_ifc_event(struct inet6_dev *idev);
-static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
-static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
-static void mld_clear_delrec(struct inet6_dev *idev);
 static bool mld_in_v1_mode(const struct inet6_dev *idev);
-static int sf_setstate(struct ifmcaddr6 *pmc);
-static void sf_markstate(struct ifmcaddr6 *pmc);
-static void ip6_mc_clear_src(struct ifmcaddr6 *pmc);
-static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca,
+static int sf_setstate(struct ifmcaddr6 *mc);
+static void sf_markstate(struct ifmcaddr6 *mc);
+static void ip6_mc_clear_src(struct ifmcaddr6 *mc);
+static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *mca,
                          int sfmode, int sfcount, const struct in6_addr 
*psfsrc,
                          int delta);
-static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
+static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *mca,
                          int sfmode, int sfcount, const struct in6_addr 
*psfsrc,
                          int delta);
 static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
@@ -113,10 +108,23 @@ int sysctl_mld_qrv __read_mostly = MLD_QRV_DEFAULT;
  *     socket join on multicast group
  */
 
-#define for_each_pmc_rcu(np, pmc)                              \
-       for (pmc = rcu_dereference(np->ipv6_mc_list);           \
-            pmc != NULL;                                       \
-            pmc = rcu_dereference(pmc->next))
+#define for_each_mc_rcu(np, mc)                                \
+       for (mc = rcu_dereference((np)->ipv6_mc_list);  \
+            mc;                                        \
+            mc = rcu_dereference(mc->next))
+
+static void mca_get(struct ifmcaddr6 *mc)
+{
+       refcount_inc(&mc->mca_refcnt);
+}
+
+static void mca_put(struct ifmcaddr6 *mc)
+{
+       if (refcount_dec_and_test(&mc->mca_refcnt)) {
+               in6_dev_put(mc->idev);
+               kfree(mc);
+       }
+}
 
 static int unsolicited_report_interval(struct inet6_dev *idev)
 {
@@ -145,7 +153,7 @@ static int __ipv6_sock_mc_join(struct sock *sk, int ifindex,
                return -EINVAL;
 
        rcu_read_lock();
-       for_each_pmc_rcu(np, mc_lst) {
+       for_each_mc_rcu(np, mc_lst) {
                if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
                    ipv6_addr_equal(&mc_lst->addr, addr)) {
                        rcu_read_unlock();
@@ -328,15 +336,15 @@ void ipv6_sock_mc_close(struct sock *sk)
 int ip6_mc_source(int add, int omode, struct sock *sk,
        struct group_source_req *pgsr)
 {
-       struct in6_addr *source, *group;
-       struct ipv6_mc_socklist *pmc;
-       struct inet6_dev *idev;
        struct ipv6_pinfo *inet6 = inet6_sk(sk);
-       struct ip6_sf_socklist *psl;
+       struct in6_addr *source, *group;
        struct net *net = sock_net(sk);
-       int i, j, rv;
+       struct ipv6_mc_socklist *mc;
+       struct ip6_sf_socklist *psl;
+       struct inet6_dev *idev;
        int leavegroup = 0;
-       int pmclocked = 0;
+       int mclocked = 0;
+       int i, j, rv;
        int err;
 
        source = &((struct sockaddr_in6 *)&pgsr->gsr_source)->sin6_addr;
@@ -354,33 +362,33 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
 
        err = -EADDRNOTAVAIL;
 
-       for_each_pmc_rcu(inet6, pmc) {
-               if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface)
+       for_each_mc_rcu(inet6, mc) {
+               if (pgsr->gsr_interface && mc->ifindex != pgsr->gsr_interface)
                        continue;
-               if (ipv6_addr_equal(&pmc->addr, group))
+               if (ipv6_addr_equal(&mc->addr, group))
                        break;
        }
-       if (!pmc) {             /* must have a prior join */
+       if (!mc) {              /* must have a prior join */
                err = -EINVAL;
                goto done;
        }
        /* if a source filter was set, must be the same mode as before */
-       if (pmc->sflist) {
-               if (pmc->sfmode != omode) {
+       if (mc->sflist) {
+               if (mc->sfmode != omode) {
                        err = -EINVAL;
                        goto done;
                }
-       } else if (pmc->sfmode != omode) {
+       } else if (mc->sfmode != omode) {
                /* allow mode switches for empty-set filters */
                ip6_mc_add_src(idev, group, omode, 0, NULL, 0);
-               ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
-               pmc->sfmode = omode;
+               ip6_mc_del_src(idev, group, mc->sfmode, 0, NULL, 0);
+               mc->sfmode = omode;
        }
 
-       write_lock(&pmc->sflock);
-       pmclocked = 1;
+       write_lock(&mc->sflock);
+       mclocked = 1;
 
-       psl = pmc->sflist;
+       psl = mc->sflist;
        if (!add) {
                if (!psl)
                        goto done;      /* err = -EADDRNOTAVAIL */
@@ -432,7 +440,8 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
                                newpsl->sl_addr[i] = psl->sl_addr[i];
                        sock_kfree_s(sk, psl, IP6_SFLSIZE(psl->sl_max));
                }
-               pmc->sflist = psl = newpsl;
+               psl = newpsl;
+               mc->sflist = psl;
        }
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
        for (i = 0; i < psl->sl_count; i++) {
@@ -448,8 +457,8 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
        /* update the interface list */
        ip6_mc_add_src(idev, group, omode, 1, source, 1);
 done:
-       if (pmclocked)
-               write_unlock(&pmc->sflock);
+       if (mclocked)
+               write_unlock(&mc->sflock);
        read_unlock_bh(&idev->lock);
        rcu_read_unlock();
        if (leavegroup)
@@ -460,12 +469,12 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
 int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf,
                    struct sockaddr_storage *list)
 {
-       const struct in6_addr *group;
-       struct ipv6_mc_socklist *pmc;
-       struct inet6_dev *idev;
        struct ipv6_pinfo *inet6 = inet6_sk(sk);
        struct ip6_sf_socklist *newpsl, *psl;
        struct net *net = sock_net(sk);
+       const struct in6_addr *group;
+       struct ipv6_mc_socklist *mc;
+       struct inet6_dev *idev;
        int leavegroup = 0;
        int i, err;
 
@@ -492,13 +501,13 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter 
*gsf,
                goto done;
        }
 
-       for_each_pmc_rcu(inet6, pmc) {
-               if (pmc->ifindex != gsf->gf_interface)
+       for_each_mc_rcu(inet6, mc) {
+               if (mc->ifindex != gsf->gf_interface)
                        continue;
-               if (ipv6_addr_equal(&pmc->addr, group))
+               if (ipv6_addr_equal(&mc->addr, group))
                        break;
        }
-       if (!pmc) {             /* must have a prior join */
+       if (!mc) {              /* must have a prior join */
                err = -EINVAL;
                goto done;
        }
@@ -524,20 +533,20 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter 
*gsf,
                }
        } else {
                newpsl = NULL;
-               (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0);
+               ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0);
        }
 
-       write_lock(&pmc->sflock);
-       psl = pmc->sflist;
+       write_lock(&mc->sflock);
+       psl = mc->sflist;
        if (psl) {
-               (void) ip6_mc_del_src(idev, group, pmc->sfmode,
-                       psl->sl_count, psl->sl_addr, 0);
+               ip6_mc_del_src(idev, group, mc->sfmode,
+                              psl->sl_count, psl->sl_addr, 0);
                sock_kfree_s(sk, psl, IP6_SFLSIZE(psl->sl_max));
        } else
-               (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
-       pmc->sflist = newpsl;
-       pmc->sfmode = gsf->gf_fmode;
-       write_unlock(&pmc->sflock);
+               ip6_mc_del_src(idev, group, mc->sfmode, 0, NULL, 0);
+       mc->sflist = newpsl;
+       mc->sfmode = gsf->gf_fmode;
+       write_unlock(&mc->sflock);
        err = 0;
 done:
        read_unlock_bh(&idev->lock);
@@ -552,7 +561,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
 {
        int err, i, count, copycount;
        const struct in6_addr *group;
-       struct ipv6_mc_socklist *pmc;
+       struct ipv6_mc_socklist *mc;
        struct inet6_dev *idev;
        struct ipv6_pinfo *inet6 = inet6_sk(sk);
        struct ip6_sf_socklist *psl;
@@ -577,16 +586,16 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter 
*gsf,
         * so reading the list is safe.
         */
 
-       for_each_pmc_rcu(inet6, pmc) {
-               if (pmc->ifindex != gsf->gf_interface)
+       for_each_mc_rcu(inet6, mc) {
+               if (mc->ifindex != gsf->gf_interface)
                        continue;
-               if (ipv6_addr_equal(group, &pmc->addr))
+               if (ipv6_addr_equal(group, &mc->addr))
                        break;
        }
-       if (!pmc)               /* must have a prior join */
+       if (!mc)                /* must have a prior join */
                goto done;
-       gsf->gf_fmode = pmc->sfmode;
-       psl = pmc->sflist;
+       gsf->gf_fmode = mc->sfmode;
+       psl = mc->sflist;
        count = psl ? psl->sl_count : 0;
        read_unlock_bh(&idev->lock);
        rcu_read_unlock();
@@ -594,7 +603,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
        copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc;
        gsf->gf_numsrc = count;
        /* changes to psl require the socket lock, and a write lock
-        * on pmc->sflock. We have the socket lock so reading here is safe.
+        * on mc->sflock. We have the socket lock so reading here is safe.
         */
        for (i = 0; i < copycount; i++, p++) {
                struct sockaddr_in6 *psin6;
@@ -623,7 +632,7 @@ bool inet6_mc_check(struct sock *sk, const struct in6_addr 
*mc_addr,
        bool rv = true;
 
        rcu_read_lock();
-       for_each_pmc_rcu(np, mc) {
+       for_each_mc_rcu(np, mc) {
                if (ipv6_addr_equal(&mc->addr, mc_addr))
                        break;
        }
@@ -723,7 +732,7 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc)
  */
 static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
 {
-       struct ifmcaddr6 *pmc;
+       struct ifmcaddr6 *mc;
 
        /* this is an "ifmcaddr6" for convenience; only the fields below
         * are actually used. In particular, the refcnt and users are not
@@ -731,98 +740,91 @@ static void mld_add_delrec(struct inet6_dev *idev, struct 
ifmcaddr6 *im)
         * for deleted items allows change reports to use common code with
         * non-deleted or query-response MCA's.
         */
-       pmc = kzalloc(sizeof(*pmc), GFP_ATOMIC);
-       if (!pmc)
+       mc = kzalloc(sizeof(*mc), GFP_ATOMIC);
+       if (!mc)
                return;
 
        spin_lock_bh(&im->mca_lock);
-       spin_lock_init(&pmc->mca_lock);
-       pmc->idev = im->idev;
+       spin_lock_init(&mc->mca_lock);
+       INIT_LIST_HEAD(&mc->list);
+       mc->idev = im->idev;
        in6_dev_hold(idev);
-       pmc->mca_addr = im->mca_addr;
-       pmc->mca_crcount = idev->mc_qrv;
-       pmc->mca_sfmode = im->mca_sfmode;
-       if (pmc->mca_sfmode == MCAST_INCLUDE) {
+       mc->mca_addr = im->mca_addr;
+       mc->mca_crcount = idev->mc_qrv;
+       mc->mca_sfmode = im->mca_sfmode;
+       if (mc->mca_sfmode == MCAST_INCLUDE) {
                struct ip6_sf_list *psf;
 
-               pmc->mca_tomb = im->mca_tomb;
-               pmc->mca_sources = im->mca_sources;
+               mc->mca_tomb = im->mca_tomb;
+               mc->mca_sources = im->mca_sources;
                im->mca_tomb = im->mca_sources = NULL;
-               for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
-                       psf->sf_crcount = pmc->mca_crcount;
+               for (psf = mc->mca_sources; psf; psf = psf->sf_next)
+                       psf->sf_crcount = mc->mca_crcount;
        }
        spin_unlock_bh(&im->mca_lock);
 
-       spin_lock_bh(&idev->mc_lock);
-       pmc->next = idev->mc_tomb;
-       idev->mc_tomb = pmc;
-       spin_unlock_bh(&idev->mc_lock);
+       spin_lock_bh(&idev->mc_tomb_lock);
+       list_add(&mc->list, &idev->mc_tomb_list);
+       spin_unlock_bh(&idev->mc_tomb_lock);
 }
 
 static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
 {
-       struct ifmcaddr6 *pmc, *pmc_prev;
+       struct ifmcaddr6 *mc = NULL, *tmp = NULL;
+       struct in6_addr *mca = &im->mca_addr;
        struct ip6_sf_list *psf;
-       struct in6_addr *pmca = &im->mca_addr;
+       bool found = false;
 
-       spin_lock_bh(&idev->mc_lock);
-       pmc_prev = NULL;
-       for (pmc = idev->mc_tomb; pmc; pmc = pmc->next) {
-               if (ipv6_addr_equal(&pmc->mca_addr, pmca))
+       spin_lock_bh(&idev->mc_tomb_lock);
+       list_for_each_entry_safe(mc, tmp, &idev->mc_tomb_list, list) {
+               if (ipv6_addr_equal(&mc->mca_addr, mca)) {
+                       list_del(&mc->list);
+                       found = true;
                        break;
-               pmc_prev = pmc;
-       }
-       if (pmc) {
-               if (pmc_prev)
-                       pmc_prev->next = pmc->next;
-               else
-                       idev->mc_tomb = pmc->next;
+               }
        }
-       spin_unlock_bh(&idev->mc_lock);
+       spin_unlock_bh(&idev->mc_tomb_lock);
 
        spin_lock_bh(&im->mca_lock);
-       if (pmc) {
-               im->idev = pmc->idev;
+       if (found) {
+               im->idev = mc->idev;
                if (im->mca_sfmode == MCAST_INCLUDE) {
-                       swap(im->mca_tomb, pmc->mca_tomb);
-                       swap(im->mca_sources, pmc->mca_sources);
+                       swap(im->mca_tomb, mc->mca_tomb);
+                       swap(im->mca_sources, mc->mca_sources);
                        for (psf = im->mca_sources; psf; psf = psf->sf_next)
                                psf->sf_crcount = idev->mc_qrv;
                } else {
                        im->mca_crcount = idev->mc_qrv;
                }
-               in6_dev_put(pmc->idev);
-               ip6_mc_clear_src(pmc);
-               kfree(pmc);
+               in6_dev_put(mc->idev);
+               ip6_mc_clear_src(mc);
+               kfree(mc);
        }
        spin_unlock_bh(&im->mca_lock);
 }
 
 static void mld_clear_delrec(struct inet6_dev *idev)
 {
-       struct ifmcaddr6 *pmc, *nextpmc;
+       struct ifmcaddr6 *mc, *tmp;
 
-       spin_lock_bh(&idev->mc_lock);
-       pmc = idev->mc_tomb;
-       idev->mc_tomb = NULL;
-       spin_unlock_bh(&idev->mc_lock);
-
-       for (; pmc; pmc = nextpmc) {
-               nextpmc = pmc->next;
-               ip6_mc_clear_src(pmc);
-               in6_dev_put(pmc->idev);
-               kfree(pmc);
+       spin_lock_bh(&idev->mc_tomb_lock);
+       list_for_each_entry_safe(mc, tmp, &idev->mc_tomb_list, list) {
+               list_del(&mc->list);
+               ip6_mc_clear_src(mc);
+               in6_dev_put(mc->idev);
+               kfree(mc);
        }
+       spin_unlock_bh(&idev->mc_tomb_lock);
 
        /* clear dead sources, too */
        read_lock_bh(&idev->lock);
-       for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
+       list_for_each_entry_safe(mc, tmp, &idev->mc_list, list) {
                struct ip6_sf_list *psf, *psf_next;
 
-               spin_lock_bh(&pmc->mca_lock);
-               psf = pmc->mca_tomb;
-               pmc->mca_tomb = NULL;
-               spin_unlock_bh(&pmc->mca_lock);
+               spin_lock_bh(&mc->mca_lock);
+               psf = mc->mca_tomb;
+               mc->mca_tomb = NULL;
+               spin_unlock_bh(&mc->mca_lock);
                for (; psf; psf = psf_next) {
                        psf_next = psf->sf_next;
                        kfree(psf);
@@ -831,19 +833,6 @@ static void mld_clear_delrec(struct inet6_dev *idev)
        read_unlock_bh(&idev->lock);
 }
 
-static void mca_get(struct ifmcaddr6 *mc)
-{
-       refcount_inc(&mc->mca_refcnt);
-}
-
-static void ma_put(struct ifmcaddr6 *mc)
-{
-       if (refcount_dec_and_test(&mc->mca_refcnt)) {
-               in6_dev_put(mc->idev);
-               kfree(mc);
-       }
-}
-
 static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
                                   const struct in6_addr *addr,
                                   unsigned int mode)
@@ -858,6 +847,7 @@ static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
 
        mc->mca_addr = *addr;
        mc->idev = idev; /* reference taken by caller */
+       INIT_LIST_HEAD(&mc->list);
        mc->mca_users = 1;
        /* mca_stamp should be updated upon changes */
        mc->mca_cstamp = mc->mca_tstamp = jiffies;
@@ -880,14 +870,13 @@ static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
 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;
+       struct ifmcaddr6 *mc;
 
        ASSERT_RTNL();
 
        /* we need to take a reference on idev */
        idev = in6_dev_get(dev);
-
        if (!idev)
                return -EINVAL;
 
@@ -898,7 +887,7 @@ static int __ipv6_dev_mc_inc(struct net_device *dev,
                return -ENODEV;
        }
 
-       for (mc = idev->mc_list; mc; mc = mc->next) {
+       list_for_each_entry(mc, &idev->mc_list, list) {
                if (ipv6_addr_equal(&mc->mca_addr, addr)) {
                        mc->mca_users++;
                        write_unlock_bh(&idev->lock);
@@ -915,8 +904,7 @@ static int __ipv6_dev_mc_inc(struct net_device *dev,
                return -ENOMEM;
        }
 
-       mc->next = idev->mc_list;
-       idev->mc_list = mc;
+       list_add(&mc->list, &idev->mc_list);
 
        /* Hold this for the code below before we unlock,
         * it is already exposed via idev->mc_list.
@@ -926,7 +914,7 @@ static int __ipv6_dev_mc_inc(struct net_device *dev,
 
        mld_del_delrec(idev, mc);
        igmp6_group_added(mc);
-       ma_put(mc);
+       mca_put(mc);
        return 0;
 }
 
@@ -941,29 +929,28 @@ EXPORT_SYMBOL(ipv6_dev_mc_inc);
  */
 int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
 {
-       struct ifmcaddr6 *ma, **map;
+       struct ifmcaddr6 *mc, *tmp;
 
        ASSERT_RTNL();
 
        write_lock_bh(&idev->lock);
-       for (map = &idev->mc_list; (ma = *map) != NULL; map = &ma->next) {
-               if (ipv6_addr_equal(&ma->mca_addr, addr)) {
-                       if (--ma->mca_users == 0) {
-                               *map = ma->next;
+       list_for_each_entry_safe(mc, tmp, &idev->mc_list, list) {
+               if (ipv6_addr_equal(&mc->mca_addr, addr)) {
+                       if (--mc->mca_users == 0) {
+                               list_del(&mc->list);
                                write_unlock_bh(&idev->lock);
-
-                               igmp6_group_dropped(ma);
-                               ip6_mc_clear_src(ma);
-
-                               ma_put(ma);
+                               igmp6_group_dropped(mc);
+                               ip6_mc_clear_src(mc);
+                               mca_put(mc);
                                return 0;
                        }
+
                        write_unlock_bh(&idev->lock);
                        return 0;
                }
        }
-       write_unlock_bh(&idev->lock);
 
+       write_unlock_bh(&idev->lock);
        return -ENOENT;
 }
 
@@ -990,19 +977,22 @@ EXPORT_SYMBOL(ipv6_dev_mc_dec);
 bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
                         const struct in6_addr *src_addr)
 {
+       bool rv = false, found = false;
        struct inet6_dev *idev;
        struct ifmcaddr6 *mc;
-       bool rv = false;
 
        rcu_read_lock();
        idev = __in6_dev_get(dev);
        if (idev) {
                read_lock_bh(&idev->lock);
-               for (mc = idev->mc_list; mc; mc = mc->next) {
-                       if (ipv6_addr_equal(&mc->mca_addr, group))
+               list_for_each_entry(mc, &idev->mc_list, list) {
+                       if (ipv6_addr_equal(&mc->mca_addr, group)) {
+                               found = true;
                                break;
+                       }
                }
-               if (mc) {
+
+               if (found) {
                        if (src_addr && !ipv6_addr_any(src_addr)) {
                                struct ip6_sf_list *psf;
 
@@ -1076,44 +1066,44 @@ static void mld_dad_stop_timer(struct inet6_dev *idev)
  *     IGMP handling (alias multicast ICMPv6 messages)
  */
 
-static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
+static void igmp6_group_queried(struct ifmcaddr6 *mc, unsigned long resptime)
 {
        unsigned long delay = resptime;
 
        /* Do not start timer for these addresses */
-       if (ipv6_addr_is_ll_all_nodes(&ma->mca_addr) ||
-           IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL)
+       if (ipv6_addr_is_ll_all_nodes(&mc->mca_addr) ||
+           IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL)
                return;
 
-       if (del_timer(&ma->mca_timer)) {
-               refcount_dec(&ma->mca_refcnt);
-               delay = ma->mca_timer.expires - jiffies;
+       if (del_timer(&mc->mca_timer)) {
+               refcount_dec(&mc->mca_refcnt);
+               delay = mc->mca_timer.expires - jiffies;
        }
 
        if (delay >= resptime)
                delay = prandom_u32() % resptime;
 
-       ma->mca_timer.expires = jiffies + delay;
-       if (!mod_timer(&ma->mca_timer, jiffies + delay))
-               refcount_inc(&ma->mca_refcnt);
-       ma->mca_flags |= MAF_TIMER_RUNNING;
+       mc->mca_timer.expires = jiffies + delay;
+       if (!mod_timer(&mc->mca_timer, jiffies + delay))
+               refcount_inc(&mc->mca_refcnt);
+       mc->mca_flags |= MAF_TIMER_RUNNING;
 }
 
 /* mark EXCLUDE-mode sources */
-static bool mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs,
+static bool mld_xmarksources(struct ifmcaddr6 *mc, int nsrcs,
                             const struct in6_addr *srcs)
 {
        struct ip6_sf_list *psf;
        int i, scount;
 
        scount = 0;
-       for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
+       for (psf = mc->mca_sources; psf; psf = psf->sf_next) {
                if (scount == nsrcs)
                        break;
                for (i = 0; i < nsrcs; i++) {
                        /* skip inactive filters */
                        if (psf->sf_count[MCAST_INCLUDE] ||
-                           pmc->mca_sfcount[MCAST_EXCLUDE] !=
+                           mc->mca_sfcount[MCAST_EXCLUDE] !=
                            psf->sf_count[MCAST_EXCLUDE])
                                break;
                        if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) {
@@ -1122,25 +1112,25 @@ static bool mld_xmarksources(struct ifmcaddr6 *pmc, int 
nsrcs,
                        }
                }
        }
-       pmc->mca_flags &= ~MAF_GSQUERY;
+       mc->mca_flags &= ~MAF_GSQUERY;
        if (scount == nsrcs)    /* all sources excluded */
                return false;
        return true;
 }
 
-static bool mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
+static bool mld_marksources(struct ifmcaddr6 *mc, int nsrcs,
                            const struct in6_addr *srcs)
 {
        struct ip6_sf_list *psf;
        int i, scount;
 
-       if (pmc->mca_sfmode == MCAST_EXCLUDE)
-               return mld_xmarksources(pmc, nsrcs, srcs);
+       if (mc->mca_sfmode == MCAST_EXCLUDE)
+               return mld_xmarksources(mc, nsrcs, srcs);
 
        /* mark INCLUDE-mode sources */
 
        scount = 0;
-       for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
+       for (psf = mc->mca_sources; psf; psf = psf->sf_next) {
                if (scount == nsrcs)
                        break;
                for (i = 0; i < nsrcs; i++) {
@@ -1152,10 +1142,10 @@ static bool mld_marksources(struct ifmcaddr6 *pmc, int 
nsrcs,
                }
        }
        if (!scount) {
-               pmc->mca_flags &= ~MAF_GSQUERY;
+               mc->mca_flags &= ~MAF_GSQUERY;
                return false;
        }
-       pmc->mca_flags |= MAF_GSQUERY;
+       mc->mca_flags |= MAF_GSQUERY;
        return true;
 }
 
@@ -1333,10 +1323,10 @@ static int mld_process_v2(struct inet6_dev *idev, 
struct mld2_query *mld,
 int igmp6_event_query(struct sk_buff *skb)
 {
        struct mld2_query *mlh2 = NULL;
-       struct ifmcaddr6 *ma;
        const struct in6_addr *group;
        unsigned long max_delay;
        struct inet6_dev *idev;
+       struct ifmcaddr6 *mc;
        struct mld_msg *mld;
        int group_type;
        int mark = 0;
@@ -1416,31 +1406,31 @@ int igmp6_event_query(struct sk_buff *skb)
 
        read_lock_bh(&idev->lock);
        if (group_type == IPV6_ADDR_ANY) {
-               for (ma = idev->mc_list; ma; ma = ma->next) {
-                       spin_lock_bh(&ma->mca_lock);
-                       igmp6_group_queried(ma, max_delay);
-                       spin_unlock_bh(&ma->mca_lock);
+               list_for_each_entry(mc, &idev->mc_list, list) {
+                       spin_lock_bh(&mc->mca_lock);
+                       igmp6_group_queried(mc, max_delay);
+                       spin_unlock_bh(&mc->mca_lock);
                }
        } else {
-               for (ma = idev->mc_list; ma; ma = ma->next) {
-                       if (!ipv6_addr_equal(group, &ma->mca_addr))
+               list_for_each_entry(mc, &idev->mc_list, list) {
+                       if (!ipv6_addr_equal(group, &mc->mca_addr))
                                continue;
-                       spin_lock_bh(&ma->mca_lock);
-                       if (ma->mca_flags & MAF_TIMER_RUNNING) {
+                       spin_lock_bh(&mc->mca_lock);
+                       if (mc->mca_flags & MAF_TIMER_RUNNING) {
                                /* gsquery <- gsquery && mark */
                                if (!mark)
-                                       ma->mca_flags &= ~MAF_GSQUERY;
+                                       mc->mca_flags &= ~MAF_GSQUERY;
                        } else {
                                /* gsquery <- mark */
                                if (mark)
-                                       ma->mca_flags |= MAF_GSQUERY;
+                                       mc->mca_flags |= MAF_GSQUERY;
                                else
-                                       ma->mca_flags &= ~MAF_GSQUERY;
+                                       mc->mca_flags &= ~MAF_GSQUERY;
                        }
-                       if (!(ma->mca_flags & MAF_GSQUERY) ||
-                           mld_marksources(ma, ntohs(mlh2->mld2q_nsrcs), 
mlh2->mld2q_srcs))
-                               igmp6_group_queried(ma, max_delay);
-                       spin_unlock_bh(&ma->mca_lock);
+                       if (!(mc->mca_flags & MAF_GSQUERY) ||
+                           mld_marksources(mc, ntohs(mlh2->mld2q_nsrcs), 
mlh2->mld2q_srcs))
+                               igmp6_group_queried(mc, max_delay);
+                       spin_unlock_bh(&mc->mca_lock);
                        break;
                }
        }
@@ -1452,8 +1442,8 @@ int igmp6_event_query(struct sk_buff *skb)
 /* called with rcu_read_lock() */
 int igmp6_event_report(struct sk_buff *skb)
 {
-       struct ifmcaddr6 *ma;
        struct inet6_dev *idev;
+       struct ifmcaddr6 *mc;
        struct mld_msg *mld;
        int addr_type;
 
@@ -1486,13 +1476,13 @@ int igmp6_event_report(struct sk_buff *skb)
         */
 
        read_lock_bh(&idev->lock);
-       for (ma = idev->mc_list; ma; ma = ma->next) {
-               if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) {
-                       spin_lock(&ma->mca_lock);
-                       if (del_timer(&ma->mca_timer))
-                               refcount_dec(&ma->mca_refcnt);
-                       ma->mca_flags &= ~(MAF_LAST_REPORTER|MAF_TIMER_RUNNING);
-                       spin_unlock(&ma->mca_lock);
+       list_for_each_entry(mc, &idev->mc_list, list) {
+               if (ipv6_addr_equal(&mc->mca_addr, &mld->mld_mca)) {
+                       spin_lock(&mc->mca_lock);
+                       if (del_timer(&mc->mca_timer))
+                               refcount_dec(&mc->mca_refcnt);
+                       mc->mca_flags &= ~(MAF_LAST_REPORTER | 
MAF_TIMER_RUNNING);
+                       spin_unlock(&mc->mca_lock);
                        break;
                }
        }
@@ -1500,7 +1490,7 @@ int igmp6_event_report(struct sk_buff *skb)
        return 0;
 }
 
-static bool is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type,
+static bool is_in(struct ifmcaddr6 *mc, struct ip6_sf_list *psf, int type,
                  int gdeleted, int sdeleted)
 {
        switch (type) {
@@ -1508,15 +1498,15 @@ static bool is_in(struct ifmcaddr6 *pmc, struct 
ip6_sf_list *psf, int type,
        case MLD2_MODE_IS_EXCLUDE:
                if (gdeleted || sdeleted)
                        return false;
-               if (!((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp)) {
-                       if (pmc->mca_sfmode == MCAST_INCLUDE)
+               if (!((mc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp)) {
+                       if (mc->mca_sfmode == MCAST_INCLUDE)
                                return true;
                        /* don't include if this source is excluded
                         * in all filters
                         */
                        if (psf->sf_count[MCAST_INCLUDE])
                                return type == MLD2_MODE_IS_INCLUDE;
-                       return pmc->mca_sfcount[MCAST_EXCLUDE] ==
+                       return mc->mca_sfcount[MCAST_EXCLUDE] ==
                                psf->sf_count[MCAST_EXCLUDE];
                }
                return false;
@@ -1527,31 +1517,31 @@ static bool is_in(struct ifmcaddr6 *pmc, struct 
ip6_sf_list *psf, int type,
        case MLD2_CHANGE_TO_EXCLUDE:
                if (gdeleted || sdeleted)
                        return false;
-               if (pmc->mca_sfcount[MCAST_EXCLUDE] == 0 ||
+               if (mc->mca_sfcount[MCAST_EXCLUDE] == 0 ||
                    psf->sf_count[MCAST_INCLUDE])
                        return false;
-               return pmc->mca_sfcount[MCAST_EXCLUDE] ==
+               return mc->mca_sfcount[MCAST_EXCLUDE] ==
                        psf->sf_count[MCAST_EXCLUDE];
        case MLD2_ALLOW_NEW_SOURCES:
                if (gdeleted || !psf->sf_crcount)
                        return false;
-               return (pmc->mca_sfmode == MCAST_INCLUDE) ^ sdeleted;
+               return (mc->mca_sfmode == MCAST_INCLUDE) ^ sdeleted;
        case MLD2_BLOCK_OLD_SOURCES:
-               if (pmc->mca_sfmode == MCAST_INCLUDE)
+               if (mc->mca_sfmode == MCAST_INCLUDE)
                        return gdeleted || (psf->sf_crcount && sdeleted);
                return psf->sf_crcount && !gdeleted && !sdeleted;
        }
        return false;
 }
 
-static int
-mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted)
+static int mld_scount(struct ifmcaddr6 *mc, int type, int gdeleted,
+                     int sdeleted)
 {
        struct ip6_sf_list *psf;
        int scount = 0;
 
-       for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
-               if (!is_in(pmc, psf, type, gdeleted, sdeleted))
+       for (psf = mc->mca_sources; psf; psf = psf->sf_next) {
+               if (!is_in(mc, psf, type, gdeleted, sdeleted))
                        continue;
                scount++;
        }
@@ -1585,21 +1575,23 @@ static void ip6_mc_hdr(struct sock *sk, struct sk_buff 
*skb,
 
 static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
 {
+       u8 ra[8] = { IPPROTO_ICMPV6, 0,
+                    IPV6_TLV_ROUTERALERT, 2,
+                    0, 0, IPV6_TLV_PADN, 0 };
        struct net_device *dev = idev->dev;
-       struct net *net = dev_net(dev);
-       struct sock *sk = net->ipv6.igmp_sk;
-       struct sk_buff *skb;
-       struct mld2_report *pmr;
-       struct in6_addr addr_buf;
-       const struct in6_addr *saddr;
        int hlen = LL_RESERVED_SPACE(dev);
        int tlen = dev->needed_tailroom;
-       unsigned int size = mtu + hlen + tlen;
+       struct net *net = dev_net(dev);
+       const struct in6_addr *saddr;
+       struct in6_addr addr_buf;
+       struct mld2_report *pmr;
+       struct sk_buff *skb;
+       unsigned int size;
+       struct sock *sk;
        int err;
-       u8 ra[8] = { IPPROTO_ICMPV6, 0,
-                    IPV6_TLV_ROUTERALERT, 2, 0, 0,
-                    IPV6_TLV_PADN, 0 };
 
+       size = mtu + hlen + tlen;
+       sk = net->ipv6.igmp_sk;
        /* we assume size > sizeof(ra) here */
        /* limit our allocations to order-0 page */
        size = min_t(int, size, SKB_MAX_ORDER(0, 0));
@@ -1639,21 +1631,22 @@ static struct sk_buff *mld_newpack(struct inet6_dev 
*idev, unsigned int mtu)
 static void mld_sendpack(struct sk_buff *skb)
 {
        struct ipv6hdr *pip6 = ipv6_hdr(skb);
-       struct mld2_report *pmr =
-                             (struct mld2_report *)skb_transport_header(skb);
+       struct net *net = dev_net(skb->dev);
        int payload_len, mldlen;
+       struct mld2_report *pmr;
        struct inet6_dev *idev;
-       struct net *net = dev_net(skb->dev);
-       int err;
-       struct flowi6 fl6;
        struct dst_entry *dst;
+       struct flowi6 fl6;
+       int err;
+
+       pmr = (struct mld2_report *)skb_transport_header(skb);
 
        rcu_read_lock();
        idev = __in6_dev_get(skb->dev);
        IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 
        payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) -
-               sizeof(*pip6);
+                     sizeof(*pip6);
        mldlen = skb_tail_pointer(skb) - skb_transport_header(skb);
        pip6->payload_len = htons(payload_len);
 
@@ -1695,19 +1688,20 @@ static void mld_sendpack(struct sk_buff *skb)
        goto out;
 }
 
-static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
+static int grec_size(struct ifmcaddr6 *mc, int type, int gdel, int sdel)
 {
-       return sizeof(struct mld2_grec) + 16 * mld_scount(pmc,type,gdel,sdel);
+       return sizeof(struct mld2_grec) + 16 * mld_scount(mc, type, gdel, sdel);
 }
 
-static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc,
-       int type, struct mld2_grec **ppgr, unsigned int mtu)
+static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *mc,
+                                 int type, struct mld2_grec **ppgr,
+                                 unsigned int mtu)
 {
        struct mld2_report *pmr;
        struct mld2_grec *pgr;
 
        if (!skb) {
-               skb = mld_newpack(pmc->idev, mtu);
+               skb = mld_newpack(mc->idev, mtu);
                if (!skb)
                        return NULL;
        }
@@ -1715,7 +1709,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, 
struct ifmcaddr6 *pmc,
        pgr->grec_type = type;
        pgr->grec_auxwords = 0;
        pgr->grec_nsrcs = 0;
-       pgr->grec_mca = pmc->mca_addr;  /* structure copy */
+       pgr->grec_mca = mc->mca_addr;   /* structure copy */
        pmr = (struct mld2_report *)skb_transport_header(skb);
        pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1);
        *ppgr = pgr;
@@ -1724,18 +1718,20 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, 
struct ifmcaddr6 *pmc,
 
 #define AVAILABLE(skb) ((skb) ? skb_availroom(skb) : 0)
 
-static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
-       int type, int gdeleted, int sdeleted, int crsend)
+static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *mc,
+                               int type, int gdeleted, int sdeleted,
+                               int crsend)
 {
-       struct inet6_dev *idev = pmc->idev;
-       struct net_device *dev = idev->dev;
-       struct mld2_report *pmr;
-       struct mld2_grec *pgr = NULL;
        struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list;
        int scount, stotal, first, isquery, truncate;
+       struct inet6_dev *idev = mc->idev;
+       struct mld2_grec *pgr = NULL;
+       struct mld2_report *pmr;
+       struct net_device *dev;
        unsigned int mtu;
 
-       if (pmc->mca_flags & MAF_NOREPORT)
+       dev = idev->dev;
+       if (mc->mca_flags & MAF_NOREPORT)
                return skb;
 
        mtu = READ_ONCE(dev->mtu);
@@ -1749,7 +1745,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, 
struct ifmcaddr6 *pmc,
 
        stotal = scount = 0;
 
-       psf_list = sdeleted ? &pmc->mca_tomb : &pmc->mca_sources;
+       psf_list = sdeleted ? &mc->mca_tomb : &mc->mca_sources;
 
        if (!*psf_list)
                goto empty_source;
@@ -1759,7 +1755,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, 
struct ifmcaddr6 *pmc,
        /* EX and TO_EX get a fresh packet, if needed */
        if (truncate) {
                if (pmr && pmr->mld2r_ngrec &&
-                   AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
+                   AVAILABLE(skb) < grec_size(mc, type, gdeleted, sdeleted)) {
                        if (skb)
                                mld_sendpack(skb);
                        skb = mld_newpack(idev, mtu);
@@ -1772,7 +1768,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, 
struct ifmcaddr6 *pmc,
 
                psf_next = psf->sf_next;
 
-               if (!is_in(pmc, psf, type, gdeleted, sdeleted) && !crsend) {
+               if (!is_in(mc, psf, type, gdeleted, sdeleted) && !crsend) {
                        psf_prev = psf;
                        continue;
                }
@@ -1780,8 +1776,8 @@ static struct sk_buff *add_grec(struct sk_buff *skb, 
struct ifmcaddr6 *pmc,
                /* Based on RFC3810 6.1. Should not send source-list change
                 * records when there is a filter mode change.
                 */
-               if (((gdeleted && pmc->mca_sfmode == MCAST_EXCLUDE) ||
-                    (!gdeleted && pmc->mca_crcount)) &&
+               if (((gdeleted && mc->mca_sfmode == MCAST_EXCLUDE) ||
+                    (!gdeleted && mc->mca_crcount)) &&
                    (type == MLD2_ALLOW_NEW_SOURCES ||
                     type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount)
                        goto decrease_sf_crcount;
@@ -1803,7 +1799,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, 
struct ifmcaddr6 *pmc,
                        scount = 0;
                }
                if (first) {
-                       skb = add_grhead(skb, pmc, type, &pgr, mtu);
+                       skb = add_grhead(skb, mc, type, &pgr, mtu);
                        first = 0;
                }
                if (!skb)
@@ -1832,49 +1828,49 @@ static struct sk_buff *add_grec(struct sk_buff *skb, 
struct ifmcaddr6 *pmc,
                if (type == MLD2_ALLOW_NEW_SOURCES ||
                    type == MLD2_BLOCK_OLD_SOURCES)
                        return skb;
-               if (pmc->mca_crcount || isquery || crsend) {
+               if (mc->mca_crcount || isquery || crsend) {
                        /* make sure we have room for group header */
                        if (skb && AVAILABLE(skb) < sizeof(struct mld2_grec)) {
                                mld_sendpack(skb);
                                skb = NULL; /* add_grhead will get a new one */
                        }
-                       skb = add_grhead(skb, pmc, type, &pgr, mtu);
+                       skb = add_grhead(skb, mc, type, &pgr, mtu);
                }
        }
        if (pgr)
                pgr->grec_nsrcs = htons(scount);
 
        if (isquery)
-               pmc->mca_flags &= ~MAF_GSQUERY; /* clear query state */
+               mc->mca_flags &= ~MAF_GSQUERY;  /* clear query state */
        return skb;
 }
 
-static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc)
+static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *mc)
 {
        struct sk_buff *skb = NULL;
        int type;
 
        read_lock_bh(&idev->lock);
-       if (!pmc) {
-               for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
-                       if (pmc->mca_flags & MAF_NOREPORT)
+       if (!mc) {
+               list_for_each_entry(mc, &idev->mc_list, list) {
+                       if (mc->mca_flags & MAF_NOREPORT)
                                continue;
-                       spin_lock_bh(&pmc->mca_lock);
-                       if (pmc->mca_sfcount[MCAST_EXCLUDE])
+                       spin_lock_bh(&mc->mca_lock);
+                       if (mc->mca_sfcount[MCAST_EXCLUDE])
                                type = MLD2_MODE_IS_EXCLUDE;
                        else
                                type = MLD2_MODE_IS_INCLUDE;
-                       skb = add_grec(skb, pmc, type, 0, 0, 0);
-                       spin_unlock_bh(&pmc->mca_lock);
+                       skb = add_grec(skb, mc, type, 0, 0, 0);
+                       spin_unlock_bh(&mc->mca_lock);
                }
        } else {
-               spin_lock_bh(&pmc->mca_lock);
-               if (pmc->mca_sfcount[MCAST_EXCLUDE])
+               spin_lock_bh(&mc->mca_lock);
+               if (mc->mca_sfcount[MCAST_EXCLUDE])
                        type = MLD2_MODE_IS_EXCLUDE;
                else
                        type = MLD2_MODE_IS_INCLUDE;
-               skb = add_grec(skb, pmc, type, 0, 0, 0);
-               spin_unlock_bh(&pmc->mca_lock);
+               skb = add_grec(skb, mc, type, 0, 0, 0);
+               spin_unlock_bh(&mc->mca_lock);
        }
        read_unlock_bh(&idev->lock);
        if (skb)
@@ -1904,94 +1900,90 @@ static void mld_clear_zeros(struct ip6_sf_list **ppsf)
 
 static void mld_send_cr(struct inet6_dev *idev)
 {
-       struct ifmcaddr6 *pmc, *pmc_prev, *pmc_next;
        struct sk_buff *skb = NULL;
+       struct ifmcaddr6 *mc, *tmp;
        int type, dtype;
 
        read_lock_bh(&idev->lock);
-       spin_lock(&idev->mc_lock);
+       spin_lock(&idev->mc_tomb_lock);
 
        /* deleted MCA's */
-       pmc_prev = NULL;
-       for (pmc = idev->mc_tomb; pmc; pmc = pmc_next) {
-               pmc_next = pmc->next;
-               if (pmc->mca_sfmode == MCAST_INCLUDE) {
+       list_for_each_entry_safe(mc, tmp, &idev->mc_tomb_list, list) {
+               if (mc->mca_sfmode == MCAST_INCLUDE) {
                        type = MLD2_BLOCK_OLD_SOURCES;
                        dtype = MLD2_BLOCK_OLD_SOURCES;
-                       skb = add_grec(skb, pmc, type, 1, 0, 0);
-                       skb = add_grec(skb, pmc, dtype, 1, 1, 0);
+                       skb = add_grec(skb, mc, type, 1, 0, 0);
+                       skb = add_grec(skb, mc, dtype, 1, 1, 0);
                }
-               if (pmc->mca_crcount) {
-                       if (pmc->mca_sfmode == MCAST_EXCLUDE) {
+               if (mc->mca_crcount) {
+                       if (mc->mca_sfmode == MCAST_EXCLUDE) {
                                type = MLD2_CHANGE_TO_INCLUDE;
-                               skb = add_grec(skb, pmc, type, 1, 0, 0);
+                               skb = add_grec(skb, mc, type, 1, 0, 0);
                        }
-                       pmc->mca_crcount--;
-                       if (pmc->mca_crcount == 0) {
-                               mld_clear_zeros(&pmc->mca_tomb);
-                               mld_clear_zeros(&pmc->mca_sources);
+                       mc->mca_crcount--;
+                       if (mc->mca_crcount == 0) {
+                               mld_clear_zeros(&mc->mca_tomb);
+                               mld_clear_zeros(&mc->mca_sources);
                        }
                }
-               if (pmc->mca_crcount == 0 && !pmc->mca_tomb &&
-                   !pmc->mca_sources) {
-                       if (pmc_prev)
-                               pmc_prev->next = pmc_next;
-                       else
-                               idev->mc_tomb = pmc_next;
-                       in6_dev_put(pmc->idev);
-                       kfree(pmc);
-               } else
-                       pmc_prev = pmc;
+               if (mc->mca_crcount == 0 && !mc->mca_tomb &&
+                   !mc->mca_sources) {
+                       list_del(&mc->list);
+                       in6_dev_put(mc->idev);
+                       kfree(mc);
+               }
        }
-       spin_unlock(&idev->mc_lock);
+       spin_unlock(&idev->mc_tomb_lock);
 
        /* change recs */
-       for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
-               spin_lock_bh(&pmc->mca_lock);
-               if (pmc->mca_sfcount[MCAST_EXCLUDE]) {
+       list_for_each_entry(mc, &idev->mc_list, list) {
+               spin_lock_bh(&mc->mca_lock);
+               if (mc->mca_sfcount[MCAST_EXCLUDE]) {
                        type = MLD2_BLOCK_OLD_SOURCES;
                        dtype = MLD2_ALLOW_NEW_SOURCES;
                } else {
                        type = MLD2_ALLOW_NEW_SOURCES;
                        dtype = MLD2_BLOCK_OLD_SOURCES;
                }
-               skb = add_grec(skb, pmc, type, 0, 0, 0);
-               skb = add_grec(skb, pmc, dtype, 0, 1, 0);       /* deleted 
sources */
+               skb = add_grec(skb, mc, type, 0, 0, 0);
+               skb = add_grec(skb, mc, dtype, 0, 1, 0);        /* deleted 
sources */
 
                /* filter mode changes */
-               if (pmc->mca_crcount) {
-                       if (pmc->mca_sfmode == MCAST_EXCLUDE)
+               if (mc->mca_crcount) {
+                       if (mc->mca_sfmode == MCAST_EXCLUDE)
                                type = MLD2_CHANGE_TO_EXCLUDE;
                        else
                                type = MLD2_CHANGE_TO_INCLUDE;
-                       skb = add_grec(skb, pmc, type, 0, 0, 0);
-                       pmc->mca_crcount--;
+                       skb = add_grec(skb, mc, type, 0, 0, 0);
+                       mc->mca_crcount--;
                }
-               spin_unlock_bh(&pmc->mca_lock);
+               spin_unlock_bh(&mc->mca_lock);
        }
        read_unlock_bh(&idev->lock);
        if (!skb)
                return;
-       (void) mld_sendpack(skb);
+       mld_sendpack(skb);
 }
 
 static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 {
+       u8 ra[8] = { IPPROTO_ICMPV6, 0,
+                    IPV6_TLV_ROUTERALERT,
+                    2, 0, 0, IPV6_TLV_PADN, 0 };
+       const struct in6_addr *snd_addr, *saddr;
+       int err, len, payload_len, full_len;
+       int hlen = LL_RESERVED_SPACE(dev);
+       int tlen = dev->needed_tailroom;
        struct net *net = dev_net(dev);
-       struct sock *sk = net->ipv6.igmp_sk;
+       struct in6_addr addr_buf;
        struct inet6_dev *idev;
+       struct dst_entry *dst;
        struct sk_buff *skb;
        struct mld_msg *hdr;
-       const struct in6_addr *snd_addr, *saddr;
-       struct in6_addr addr_buf;
-       int hlen = LL_RESERVED_SPACE(dev);
-       int tlen = dev->needed_tailroom;
-       int err, len, payload_len, full_len;
-       u8 ra[8] = { IPPROTO_ICMPV6, 0,
-                    IPV6_TLV_ROUTERALERT, 2, 0, 0,
-                    IPV6_TLV_PADN, 0 };
        struct flowi6 fl6;
-       struct dst_entry *dst;
+       struct sock *sk;
+
+       sk = net->ipv6.igmp_sk;
 
        if (type == ICMPV6_MGM_REDUCTION)
                snd_addr = &in6addr_linklocal_allrouters;
@@ -2074,7 +2066,7 @@ static void igmp6_send(struct in6_addr *addr, struct 
net_device *dev, int type)
 static void mld_send_initial_cr(struct inet6_dev *idev)
 {
        struct sk_buff *skb;
-       struct ifmcaddr6 *pmc;
+       struct ifmcaddr6 *mc;
        int type;
 
        if (mld_in_v1_mode(idev))
@@ -2082,14 +2074,14 @@ static void mld_send_initial_cr(struct inet6_dev *idev)
 
        skb = NULL;
        read_lock_bh(&idev->lock);
-       for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
-               spin_lock_bh(&pmc->mca_lock);
-               if (pmc->mca_sfcount[MCAST_EXCLUDE])
+       list_for_each_entry(mc, &idev->mc_list, list) {
+               spin_lock_bh(&mc->mca_lock);
+               if (mc->mca_sfcount[MCAST_EXCLUDE])
                        type = MLD2_CHANGE_TO_EXCLUDE;
                else
                        type = MLD2_ALLOW_NEW_SOURCES;
-               skb = add_grec(skb, pmc, type, 0, 0, 1);
-               spin_unlock_bh(&pmc->mca_lock);
+               skb = add_grec(skb, mc, type, 0, 0, 1);
+               spin_unlock_bh(&mc->mca_lock);
        }
        read_unlock_bh(&idev->lock);
        if (skb)
@@ -2122,14 +2114,14 @@ static void mld_dad_timer_expire(struct timer_list *t)
        in6_dev_put(idev);
 }
 
-static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
-       const struct in6_addr *psfsrc)
+static int ip6_mc_del1_src(struct ifmcaddr6 *mc, int sfmode,
+                          const struct in6_addr *psfsrc)
 {
        struct ip6_sf_list *psf, *psf_prev;
        int rv = 0;
 
        psf_prev = NULL;
-       for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
+       for (psf = mc->mca_sources; psf; psf = psf->sf_next) {
                if (ipv6_addr_equal(&psf->sf_addr, psfsrc))
                        break;
                psf_prev = psf;
@@ -2140,78 +2132,83 @@ static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int 
sfmode,
        }
        psf->sf_count[sfmode]--;
        if (!psf->sf_count[MCAST_INCLUDE] && !psf->sf_count[MCAST_EXCLUDE]) {
-               struct inet6_dev *idev = pmc->idev;
+               struct inet6_dev *idev = mc->idev;
 
                /* no more filters for this source */
                if (psf_prev)
                        psf_prev->sf_next = psf->sf_next;
                else
-                       pmc->mca_sources = psf->sf_next;
-               if (psf->sf_oldin && !(pmc->mca_flags & MAF_NOREPORT) &&
+                       mc->mca_sources = psf->sf_next;
+               if (psf->sf_oldin && !(mc->mca_flags & MAF_NOREPORT) &&
                    !mld_in_v1_mode(idev)) {
                        psf->sf_crcount = idev->mc_qrv;
-                       psf->sf_next = pmc->mca_tomb;
-                       pmc->mca_tomb = psf;
+                       psf->sf_next = mc->mca_tomb;
+                       mc->mca_tomb = psf;
                        rv = 1;
-               } else
+               } else {
                        kfree(psf);
+               }
        }
        return rv;
 }
 
-static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca,
+static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *mca,
                          int sfmode, int sfcount, const struct in6_addr 
*psfsrc,
                          int delta)
 {
-       struct ifmcaddr6 *pmc;
-       int     changerec = 0;
-       int     i, err;
+       struct ifmcaddr6 *mc;
+       bool found = false;
+       int changerec = 0;
+       int i, err;
 
        if (!idev)
                return -ENODEV;
        read_lock_bh(&idev->lock);
-       for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
-               if (ipv6_addr_equal(pmca, &pmc->mca_addr))
+       list_for_each_entry(mc, &idev->mc_list, list) {
+               if (ipv6_addr_equal(mca, &mc->mca_addr)) {
+                       found = true;
                        break;
+               }
        }
-       if (!pmc) {
+       if (!found) {
                /* MCA not found?? bug */
                read_unlock_bh(&idev->lock);
                return -ESRCH;
        }
-       spin_lock_bh(&pmc->mca_lock);
-       sf_markstate(pmc);
+       spin_lock_bh(&mc->mca_lock);
+       sf_markstate(mc);
        if (!delta) {
-               if (!pmc->mca_sfcount[sfmode]) {
-                       spin_unlock_bh(&pmc->mca_lock);
+               if (!mc->mca_sfcount[sfmode]) {
+                       spin_unlock_bh(&mc->mca_lock);
                        read_unlock_bh(&idev->lock);
                        return -EINVAL;
                }
-               pmc->mca_sfcount[sfmode]--;
+               mc->mca_sfcount[sfmode]--;
        }
        err = 0;
        for (i = 0; i < sfcount; i++) {
-               int rv = ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]);
+               int rv = ip6_mc_del1_src(mc, sfmode, &psfsrc[i]);
 
                changerec |= rv > 0;
                if (!err && rv < 0)
                        err = rv;
        }
-       if (pmc->mca_sfmode == MCAST_EXCLUDE &&
-           pmc->mca_sfcount[MCAST_EXCLUDE] == 0 &&
-           pmc->mca_sfcount[MCAST_INCLUDE]) {
+       if (mc->mca_sfmode == MCAST_EXCLUDE &&
+           mc->mca_sfcount[MCAST_EXCLUDE] == 0 &&
+           mc->mca_sfcount[MCAST_INCLUDE]) {
                struct ip6_sf_list *psf;
 
                /* filter mode change */
-               pmc->mca_sfmode = MCAST_INCLUDE;
-               pmc->mca_crcount = idev->mc_qrv;
-               idev->mc_ifc_count = pmc->mca_crcount;
-               for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
+               mc->mca_sfmode = MCAST_INCLUDE;
+               mc->mca_crcount = idev->mc_qrv;
+               idev->mc_ifc_count = mc->mca_crcount;
+               for (psf = mc->mca_sources; psf; psf = psf->sf_next)
                        psf->sf_crcount = 0;
-               mld_ifc_event(pmc->idev);
-       } else if (sf_setstate(pmc) || changerec)
-               mld_ifc_event(pmc->idev);
-       spin_unlock_bh(&pmc->mca_lock);
+               mld_ifc_event(mc->idev);
+       } else if (sf_setstate(mc) || changerec) {
+               mld_ifc_event(mc->idev);
+       }
+       spin_unlock_bh(&mc->mca_lock);
        read_unlock_bh(&idev->lock);
        return err;
 }
@@ -2219,13 +2216,13 @@ static int ip6_mc_del_src(struct inet6_dev *idev, const 
struct in6_addr *pmca,
 /*
  * Add multicast single-source filter to the interface list
  */
-static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode,
-       const struct in6_addr *psfsrc)
+static int ip6_mc_add1_src(struct ifmcaddr6 *mc, int sfmode,
+                          const struct in6_addr *psfsrc)
 {
        struct ip6_sf_list *psf, *psf_prev;
 
        psf_prev = NULL;
-       for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
+       for (psf = mc->mca_sources; psf; psf = psf->sf_next) {
                if (ipv6_addr_equal(&psf->sf_addr, psfsrc))
                        break;
                psf_prev = psf;
@@ -2239,36 +2236,37 @@ static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int 
sfmode,
                if (psf_prev) {
                        psf_prev->sf_next = psf;
                } else
-                       pmc->mca_sources = psf;
+                       mc->mca_sources = psf;
        }
        psf->sf_count[sfmode]++;
        return 0;
 }
 
-static void sf_markstate(struct ifmcaddr6 *pmc)
+static void sf_markstate(struct ifmcaddr6 *mc)
 {
+       int mca_xcount = mc->mca_sfcount[MCAST_EXCLUDE];
        struct ip6_sf_list *psf;
-       int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE];
 
-       for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
-               if (pmc->mca_sfcount[MCAST_EXCLUDE]) {
+       for (psf = mc->mca_sources; psf; psf = psf->sf_next) {
+               if (mc->mca_sfcount[MCAST_EXCLUDE]) {
                        psf->sf_oldin = mca_xcount ==
                                psf->sf_count[MCAST_EXCLUDE] &&
                                !psf->sf_count[MCAST_INCLUDE];
                } else
                        psf->sf_oldin = psf->sf_count[MCAST_INCLUDE] != 0;
+       }
 }
 
-static int sf_setstate(struct ifmcaddr6 *pmc)
+static int sf_setstate(struct ifmcaddr6 *mc)
 {
+       int mca_xcount = mc->mca_sfcount[MCAST_EXCLUDE];
        struct ip6_sf_list *psf, *dpsf;
-       int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE];
-       int qrv = pmc->idev->mc_qrv;
+       int qrv = mc->idev->mc_qrv;
        int new_in, rv;
 
        rv = 0;
-       for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
-               if (pmc->mca_sfcount[MCAST_EXCLUDE]) {
+       for (psf = mc->mca_sources; psf; psf = psf->sf_next) {
+               if (mc->mca_sfcount[MCAST_EXCLUDE]) {
                        new_in = mca_xcount == psf->sf_count[MCAST_EXCLUDE] &&
                                !psf->sf_count[MCAST_INCLUDE];
                } else
@@ -2277,7 +2275,7 @@ static int sf_setstate(struct ifmcaddr6 *pmc)
                        if (!psf->sf_oldin) {
                                struct ip6_sf_list *prev = NULL;
 
-                               for (dpsf = pmc->mca_tomb; dpsf;
+                               for (dpsf = mc->mca_tomb; dpsf;
                                     dpsf = dpsf->sf_next) {
                                        if (ipv6_addr_equal(&dpsf->sf_addr,
                                            &psf->sf_addr))
@@ -2288,7 +2286,7 @@ static int sf_setstate(struct ifmcaddr6 *pmc)
                                        if (prev)
                                                prev->sf_next = dpsf->sf_next;
                                        else
-                                               pmc->mca_tomb = dpsf->sf_next;
+                                               mc->mca_tomb = dpsf->sf_next;
                                        kfree(dpsf);
                                }
                                psf->sf_crcount = qrv;
@@ -2300,7 +2298,7 @@ static int sf_setstate(struct ifmcaddr6 *pmc)
                         * add or update "delete" records if an active filter
                         * is now inactive
                         */
-                       for (dpsf = pmc->mca_tomb; dpsf; dpsf = dpsf->sf_next)
+                       for (dpsf = mc->mca_tomb; dpsf; dpsf = dpsf->sf_next)
                                if (ipv6_addr_equal(&dpsf->sf_addr,
                                    &psf->sf_addr))
                                        break;
@@ -2309,9 +2307,9 @@ static int sf_setstate(struct ifmcaddr6 *pmc)
                                if (!dpsf)
                                        continue;
                                *dpsf = *psf;
-                               /* pmc->mca_lock held by callers */
-                               dpsf->sf_next = pmc->mca_tomb;
-                               pmc->mca_tomb = dpsf;
+                               /* mc->mca_lock held by callers */
+                               dpsf->sf_next = mc->mca_tomb;
+                               mc->mca_tomb = dpsf;
                        }
                        dpsf->sf_crcount = qrv;
                        rv++;
@@ -2323,35 +2321,39 @@ static int sf_setstate(struct ifmcaddr6 *pmc)
 /*
  * Add multicast source filter list to the interface list
  */
-static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
+static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *mca,
                          int sfmode, int sfcount, const struct in6_addr 
*psfsrc,
                          int delta)
 {
-       struct ifmcaddr6 *pmc;
-       int     isexclude;
-       int     i, err;
+       struct ifmcaddr6 *mc;
+       bool found = false;
+       int isexclude;
+       int i, err;
 
        if (!idev)
                return -ENODEV;
+
        read_lock_bh(&idev->lock);
-       for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
-               if (ipv6_addr_equal(pmca, &pmc->mca_addr))
+       list_for_each_entry(mc, &idev->mc_list, list) {
+               if (ipv6_addr_equal(mca, &mc->mca_addr)) {
+                       found = true;
                        break;
+               }
        }
-       if (!pmc) {
+       if (!found) {
                /* MCA not found?? bug */
                read_unlock_bh(&idev->lock);
                return -ESRCH;
        }
-       spin_lock_bh(&pmc->mca_lock);
+       spin_lock_bh(&mc->mca_lock);
 
-       sf_markstate(pmc);
-       isexclude = pmc->mca_sfmode == MCAST_EXCLUDE;
+       sf_markstate(mc);
+       isexclude = mc->mca_sfmode == MCAST_EXCLUDE;
        if (!delta)
-               pmc->mca_sfcount[sfmode]++;
+               mc->mca_sfcount[sfmode]++;
        err = 0;
        for (i = 0; i < sfcount; i++) {
-               err = ip6_mc_add1_src(pmc, sfmode, &psfsrc[i]);
+               err = ip6_mc_add1_src(mc, sfmode, &psfsrc[i]);
                if (err)
                        break;
        }
@@ -2359,72 +2361,72 @@ static int ip6_mc_add_src(struct inet6_dev *idev, const 
struct in6_addr *pmca,
                int j;
 
                if (!delta)
-                       pmc->mca_sfcount[sfmode]--;
+                       mc->mca_sfcount[sfmode]--;
                for (j = 0; j < i; j++)
-                       ip6_mc_del1_src(pmc, sfmode, &psfsrc[j]);
-       } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) {
+                       ip6_mc_del1_src(mc, sfmode, &psfsrc[j]);
+       } else if (isexclude != (mc->mca_sfcount[MCAST_EXCLUDE] != 0)) {
                struct ip6_sf_list *psf;
 
                /* filter mode change */
-               if (pmc->mca_sfcount[MCAST_EXCLUDE])
-                       pmc->mca_sfmode = MCAST_EXCLUDE;
-               else if (pmc->mca_sfcount[MCAST_INCLUDE])
-                       pmc->mca_sfmode = MCAST_INCLUDE;
+               if (mc->mca_sfcount[MCAST_EXCLUDE])
+                       mc->mca_sfmode = MCAST_EXCLUDE;
+               else if (mc->mca_sfcount[MCAST_INCLUDE])
+                       mc->mca_sfmode = MCAST_INCLUDE;
                /* else no filters; keep old mode for reports */
 
-               pmc->mca_crcount = idev->mc_qrv;
-               idev->mc_ifc_count = pmc->mca_crcount;
-               for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
+               mc->mca_crcount = idev->mc_qrv;
+               idev->mc_ifc_count = mc->mca_crcount;
+               for (psf = mc->mca_sources; psf; psf = psf->sf_next)
                        psf->sf_crcount = 0;
                mld_ifc_event(idev);
-       } else if (sf_setstate(pmc))
+       } else if (sf_setstate(mc))
                mld_ifc_event(idev);
-       spin_unlock_bh(&pmc->mca_lock);
+       spin_unlock_bh(&mc->mca_lock);
        read_unlock_bh(&idev->lock);
        return err;
 }
 
-static void ip6_mc_clear_src(struct ifmcaddr6 *pmc)
+static void ip6_mc_clear_src(struct ifmcaddr6 *mc)
 {
        struct ip6_sf_list *psf, *nextpsf;
 
-       for (psf = pmc->mca_tomb; psf; psf = nextpsf) {
+       for (psf = mc->mca_tomb; psf; psf = nextpsf) {
                nextpsf = psf->sf_next;
                kfree(psf);
        }
-       pmc->mca_tomb = NULL;
-       for (psf = pmc->mca_sources; psf; psf = nextpsf) {
+       mc->mca_tomb = NULL;
+       for (psf = mc->mca_sources; psf; psf = nextpsf) {
                nextpsf = psf->sf_next;
                kfree(psf);
        }
-       pmc->mca_sources = NULL;
-       pmc->mca_sfmode = MCAST_EXCLUDE;
-       pmc->mca_sfcount[MCAST_INCLUDE] = 0;
-       pmc->mca_sfcount[MCAST_EXCLUDE] = 1;
+       mc->mca_sources = NULL;
+       mc->mca_sfmode = MCAST_EXCLUDE;
+       mc->mca_sfcount[MCAST_INCLUDE] = 0;
+       mc->mca_sfcount[MCAST_EXCLUDE] = 1;
 }
 
 
-static void igmp6_join_group(struct ifmcaddr6 *ma)
+static void igmp6_join_group(struct ifmcaddr6 *mc)
 {
        unsigned long delay;
 
-       if (ma->mca_flags & MAF_NOREPORT)
+       if (mc->mca_flags & MAF_NOREPORT)
                return;
 
-       igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
+       igmp6_send(&mc->mca_addr, mc->idev->dev, ICMPV6_MGM_REPORT);
 
-       delay = prandom_u32() % unsolicited_report_interval(ma->idev);
+       delay = prandom_u32() % unsolicited_report_interval(mc->idev);
 
-       spin_lock_bh(&ma->mca_lock);
-       if (del_timer(&ma->mca_timer)) {
-               refcount_dec(&ma->mca_refcnt);
-               delay = ma->mca_timer.expires - jiffies;
+       spin_lock_bh(&mc->mca_lock);
+       if (del_timer(&mc->mca_timer)) {
+               refcount_dec(&mc->mca_refcnt);
+               delay = mc->mca_timer.expires - jiffies;
        }
 
-       if (!mod_timer(&ma->mca_timer, jiffies + delay))
-               refcount_inc(&ma->mca_refcnt);
-       ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER;
-       spin_unlock_bh(&ma->mca_lock);
+       if (!mod_timer(&mc->mca_timer, jiffies + delay))
+               refcount_inc(&mc->mca_refcnt);
+       mc->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER;
+       spin_unlock_bh(&mc->mca_lock);
 }
 
 static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
@@ -2446,15 +2448,15 @@ static int ip6_mc_leave_src(struct sock *sk, struct 
ipv6_mc_socklist *iml,
        return err;
 }
 
-static void igmp6_leave_group(struct ifmcaddr6 *ma)
+static void igmp6_leave_group(struct ifmcaddr6 *mc)
 {
-       if (mld_in_v1_mode(ma->idev)) {
-               if (ma->mca_flags & MAF_LAST_REPORTER)
-                       igmp6_send(&ma->mca_addr, ma->idev->dev,
-                               ICMPV6_MGM_REDUCTION);
+       if (mld_in_v1_mode(mc->idev)) {
+               if (mc->mca_flags & MAF_LAST_REPORTER)
+                       igmp6_send(&mc->mca_addr, mc->idev->dev,
+                                  ICMPV6_MGM_REDUCTION);
        } else {
-               mld_add_delrec(ma->idev, ma);
-               mld_ifc_event(ma->idev);
+               mld_add_delrec(mc->idev, mc);
+               mld_ifc_event(mc->idev);
        }
 }
 
@@ -2491,31 +2493,31 @@ static void mld_ifc_event(struct inet6_dev *idev)
 
 static void igmp6_timer_handler(struct timer_list *t)
 {
-       struct ifmcaddr6 *ma = from_timer(ma, t, mca_timer);
+       struct ifmcaddr6 *mc = from_timer(mc, t, mca_timer);
 
-       if (mld_in_v1_mode(ma->idev))
-               igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
+       if (mld_in_v1_mode(mc->idev))
+               igmp6_send(&mc->mca_addr, mc->idev->dev, ICMPV6_MGM_REPORT);
        else
-               mld_send_report(ma->idev, ma);
+               mld_send_report(mc->idev, mc);
 
-       spin_lock(&ma->mca_lock);
-       ma->mca_flags |=  MAF_LAST_REPORTER;
-       ma->mca_flags &= ~MAF_TIMER_RUNNING;
-       spin_unlock(&ma->mca_lock);
-       ma_put(ma);
+       spin_lock(&mc->mca_lock);
+       mc->mca_flags |=  MAF_LAST_REPORTER;
+       mc->mca_flags &= ~MAF_TIMER_RUNNING;
+       spin_unlock(&mc->mca_lock);
+       mca_put(mc);
 }
 
 /* Device changing type */
 
 void ipv6_mc_unmap(struct inet6_dev *idev)
 {
-       struct ifmcaddr6 *i;
+       struct ifmcaddr6 *mc, *tmp;
 
        /* Install multicast list, except for all-nodes (already installed) */
 
        read_lock_bh(&idev->lock);
-       for (i = idev->mc_list; i; i = i->next)
-               igmp6_group_dropped(i);
+       list_for_each_entry_safe(mc, tmp, &idev->mc_list, list)
+               igmp6_group_dropped(mc);
        read_unlock_bh(&idev->lock);
 }
 
@@ -2528,14 +2530,14 @@ void ipv6_mc_remap(struct inet6_dev *idev)
 
 void ipv6_mc_down(struct inet6_dev *idev)
 {
-       struct ifmcaddr6 *i;
+       struct ifmcaddr6 *mc, *tmp;
 
        /* Withdraw multicast list */
 
        read_lock_bh(&idev->lock);
 
-       for (i = idev->mc_list; i; i = i->next)
-               igmp6_group_dropped(i);
+       list_for_each_entry_safe(mc, tmp, &idev->mc_list, list)
+               igmp6_group_dropped(mc);
 
        /* Should stop timer after group drop. or we will
         * start timer again in mld_ifc_event()
@@ -2559,15 +2561,15 @@ static void ipv6_mc_reset(struct inet6_dev *idev)
 
 void ipv6_mc_up(struct inet6_dev *idev)
 {
-       struct ifmcaddr6 *i;
+       struct ifmcaddr6 *mc, *tmp;
 
        /* Install multicast list, except for all-nodes (already installed) */
 
        read_lock_bh(&idev->lock);
        ipv6_mc_reset(idev);
-       for (i = idev->mc_list; i; i = i->next) {
-               mld_del_delrec(idev, i);
-               igmp6_group_added(i);
+       list_for_each_entry_safe(mc, tmp, &idev->mc_list, list) {
+               mld_del_delrec(idev, mc);
+               igmp6_group_added(mc);
        }
        read_unlock_bh(&idev->lock);
 }
@@ -2577,10 +2579,11 @@ void ipv6_mc_up(struct inet6_dev *idev)
 void ipv6_mc_init_dev(struct inet6_dev *idev)
 {
        write_lock_bh(&idev->lock);
-       spin_lock_init(&idev->mc_lock);
+       spin_lock_init(&idev->mc_tomb_lock);
        idev->mc_gq_running = 0;
        timer_setup(&idev->mc_gq_timer, mld_gq_timer_expire, 0);
-       idev->mc_tomb = NULL;
+       INIT_LIST_HEAD(&idev->mc_tomb_list);
+       INIT_LIST_HEAD(&idev->mc_list);
        idev->mc_ifc_count = 0;
        timer_setup(&idev->mc_ifc_timer, mld_ifc_timer_expire, 0);
        timer_setup(&idev->mc_dad_timer, mld_dad_timer_expire, 0);
@@ -2594,7 +2597,7 @@ void ipv6_mc_init_dev(struct inet6_dev *idev)
 
 void ipv6_mc_destroy_dev(struct inet6_dev *idev)
 {
-       struct ifmcaddr6 *i;
+       struct ifmcaddr6 *mc, *tmp;
 
        /* Deactivate timers */
        ipv6_mc_down(idev);
@@ -2611,12 +2614,11 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
                __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters);
 
        write_lock_bh(&idev->lock);
-       while ((i = idev->mc_list) != NULL) {
-               idev->mc_list = i->next;
-
+       list_for_each_entry_safe(mc, tmp, &idev->mc_list, list) {
+               list_del(&mc->list);
                write_unlock_bh(&idev->lock);
-               ip6_mc_clear_src(i);
-               ma_put(i);
+               ip6_mc_clear_src(mc);
+               mca_put(mc);
                write_lock_bh(&idev->lock);
        }
        write_unlock_bh(&idev->lock);
@@ -2624,14 +2626,14 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
 
 static void ipv6_mc_rejoin_groups(struct inet6_dev *idev)
 {
-       struct ifmcaddr6 *pmc;
+       struct ifmcaddr6 *mc;
 
        ASSERT_RTNL();
 
        if (mld_in_v1_mode(idev)) {
                read_lock_bh(&idev->lock);
-               for (pmc = idev->mc_list; pmc; pmc = pmc->next)
-                       igmp6_join_group(pmc);
+               list_for_each_entry(mc, &idev->mc_list, list)
+                       igmp6_join_group(mc);
                read_unlock_bh(&idev->lock);
        } else
                mld_send_report(idev, NULL);
@@ -2671,57 +2673,64 @@ struct igmp6_mc_iter_state {
 
 static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
 {
-       struct ifmcaddr6 *im = NULL;
        struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
        struct net *net = seq_file_net(seq);
+       struct ifmcaddr6 *mc;
 
        state->idev = NULL;
        for_each_netdev_rcu(net, state->dev) {
                struct inet6_dev *idev;
+
                idev = __in6_dev_get(state->dev);
                if (!idev)
                        continue;
+
                read_lock_bh(&idev->lock);
-               im = idev->mc_list;
-               if (im) {
+               list_for_each_entry(mc, &idev->mc_list, list) {
                        state->idev = idev;
-                       break;
+                       return mc;
                }
                read_unlock_bh(&idev->lock);
        }
-       return im;
+       return NULL;
 }
 
-static struct ifmcaddr6 *igmp6_mc_get_next(struct seq_file *seq, struct 
ifmcaddr6 *im)
+static struct ifmcaddr6 *igmp6_mc_get_next(struct seq_file *seq, struct 
ifmcaddr6 *mc)
 {
        struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
 
-       im = im->next;
-       while (!im) {
-               if (likely(state->idev))
+       list_for_each_entry_continue(mc, &state->idev->mc_list, list)
+               return mc;
+
+       mc = NULL;
+
+       while (!mc) {
+               if (state->idev)
                        read_unlock_bh(&state->idev->lock);
 
                state->dev = next_net_device_rcu(state->dev);
                if (!state->dev) {
                        state->idev = NULL;
-                       break;
+                       return NULL;
                }
                state->idev = __in6_dev_get(state->dev);
                if (!state->idev)
                        continue;
                read_lock_bh(&state->idev->lock);
-               im = state->idev->mc_list;
+               mc = list_first_entry_or_null(&state->idev->mc_list,
+                                             struct ifmcaddr6, list);
        }
-       return im;
+       return mc;
 }
 
 static struct ifmcaddr6 *igmp6_mc_get_idx(struct seq_file *seq, loff_t pos)
 {
-       struct ifmcaddr6 *im = igmp6_mc_get_first(seq);
-       if (im)
-               while (pos && (im = igmp6_mc_get_next(seq, im)) != NULL)
+       struct ifmcaddr6 *mc = igmp6_mc_get_first(seq);
+
+       if (mc)
+               while (pos && (mc = igmp6_mc_get_next(seq, mc)) != NULL)
                        --pos;
-       return pos ? NULL : im;
+       return pos ? NULL : mc;
 }
 
 static void *igmp6_mc_seq_start(struct seq_file *seq, loff_t *pos)
@@ -2733,10 +2742,10 @@ static void *igmp6_mc_seq_start(struct seq_file *seq, 
loff_t *pos)
 
 static void *igmp6_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-       struct ifmcaddr6 *im = igmp6_mc_get_next(seq, v);
+       struct ifmcaddr6 *mc = igmp6_mc_get_next(seq, v);
 
        ++*pos;
-       return im;
+       return mc;
 }
 
 static void igmp6_mc_seq_stop(struct seq_file *seq, void *v)
@@ -2754,16 +2763,16 @@ static void igmp6_mc_seq_stop(struct seq_file *seq, 
void *v)
 
 static int igmp6_mc_seq_show(struct seq_file *seq, void *v)
 {
-       struct ifmcaddr6 *im = (struct ifmcaddr6 *)v;
+       struct ifmcaddr6 *mc = (struct ifmcaddr6 *)v;
        struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
 
        seq_printf(seq,
                   "%-4d %-15s %pi6 %5d %08X %ld\n",
                   state->dev->ifindex, state->dev->name,
-                  &im->mca_addr,
-                  im->mca_users, im->mca_flags,
-                  (im->mca_flags&MAF_TIMER_RUNNING) ?
-                  jiffies_to_clock_t(im->mca_timer.expires-jiffies) : 0);
+                  &mc->mca_addr,
+                  mc->mca_users, mc->mca_flags,
+                  (mc->mca_flags & MAF_TIMER_RUNNING) ?
+                  jiffies_to_clock_t(mc->mca_timer.expires - jiffies) : 0);
        return 0;
 }
 
@@ -2778,51 +2787,61 @@ struct igmp6_mcf_iter_state {
        struct seq_net_private p;
        struct net_device *dev;
        struct inet6_dev *idev;
-       struct ifmcaddr6 *im;
+       struct ifmcaddr6 *mc;
 };
 
 #define igmp6_mcf_seq_private(seq)     ((struct igmp6_mcf_iter_state 
*)(seq)->private)
 
 static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
 {
-       struct ip6_sf_list *psf = NULL;
-       struct ifmcaddr6 *im = NULL;
        struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
        struct net *net = seq_file_net(seq);
+       struct ip6_sf_list *psf = NULL;
+       struct ifmcaddr6 *mc = NULL;
 
        state->idev = NULL;
-       state->im = NULL;
+       state->mc = NULL;
        for_each_netdev_rcu(net, state->dev) {
                struct inet6_dev *idev;
+
                idev = __in6_dev_get(state->dev);
                if (unlikely(idev == NULL))
                        continue;
                read_lock_bh(&idev->lock);
-               im = idev->mc_list;
-               if (likely(im)) {
-                       spin_lock_bh(&im->mca_lock);
-                       psf = im->mca_sources;
+               mc = list_first_entry_or_null(&idev->mc_list,
+                                             struct ifmcaddr6, list);
+               if (likely(mc)) {
+                       spin_lock_bh(&mc->mca_lock);
+                       psf = mc->mca_sources;
                        if (likely(psf)) {
-                               state->im = im;
+                               state->mc = mc;
                                state->idev = idev;
                                break;
                        }
-                       spin_unlock_bh(&im->mca_lock);
+                       spin_unlock_bh(&mc->mca_lock);
                }
                read_unlock_bh(&idev->lock);
        }
        return psf;
 }
 
-static struct ip6_sf_list *igmp6_mcf_get_next(struct seq_file *seq, struct 
ip6_sf_list *psf)
+static struct ip6_sf_list *igmp6_mcf_get_next(struct seq_file *seq,
+                                             struct ip6_sf_list *psf)
 {
        struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
 
        psf = psf->sf_next;
        while (!psf) {
-               spin_unlock_bh(&state->im->mca_lock);
-               state->im = state->im->next;
-               while (!state->im) {
+               spin_unlock_bh(&state->mc->mca_lock);
+               list_for_each_entry_continue(state->mc, &state->idev->mc_list, 
list) {
+                       spin_lock_bh(&state->mc->mca_lock);
+                       psf = state->mc->mca_sources;
+                       goto out;
+               }
+
+               state->mc = NULL;
+
+               while (!state->mc) {
                        if (likely(state->idev))
                                read_unlock_bh(&state->idev->lock);
 
@@ -2835,12 +2854,13 @@ static struct ip6_sf_list *igmp6_mcf_get_next(struct 
seq_file *seq, struct ip6_s
                        if (!state->idev)
                                continue;
                        read_lock_bh(&state->idev->lock);
-                       state->im = state->idev->mc_list;
+                       state->mc = 
list_first_entry_or_null(&state->idev->mc_list,
+                                                            struct ifmcaddr6, 
list);
                }
-               if (!state->im)
+               if (!state->mc)
                        break;
-               spin_lock_bh(&state->im->mca_lock);
-               psf = state->im->mca_sources;
+               spin_lock_bh(&state->mc->mca_lock);
+               psf = state->mc->mca_sources;
        }
 out:
        return psf;
@@ -2849,6 +2869,7 @@ static struct ip6_sf_list *igmp6_mcf_get_next(struct 
seq_file *seq, struct ip6_s
 static struct ip6_sf_list *igmp6_mcf_get_idx(struct seq_file *seq, loff_t pos)
 {
        struct ip6_sf_list *psf = igmp6_mcf_get_first(seq);
+
        if (psf)
                while (pos && (psf = igmp6_mcf_get_next(seq, psf)) != NULL)
                        --pos;
@@ -2865,6 +2886,7 @@ static void *igmp6_mcf_seq_start(struct seq_file *seq, 
loff_t *pos)
 static void *igmp6_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        struct ip6_sf_list *psf;
+
        if (v == SEQ_START_TOKEN)
                psf = igmp6_mcf_get_first(seq);
        else
@@ -2877,9 +2899,10 @@ static void igmp6_mcf_seq_stop(struct seq_file *seq, 
void *v)
        __releases(RCU)
 {
        struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
-       if (likely(state->im)) {
-               spin_unlock_bh(&state->im->mca_lock);
-               state->im = NULL;
+
+       if (likely(state->mc)) {
+               spin_unlock_bh(&state->mc->mca_lock);
+               state->mc = NULL;
        }
        if (likely(state->idev)) {
                read_unlock_bh(&state->idev->lock);
@@ -2900,7 +2923,7 @@ static int igmp6_mcf_seq_show(struct seq_file *seq, void 
*v)
                seq_printf(seq,
                           "%3d %6.6s %pi6 %pi6 %6lu %6lu\n",
                           state->dev->ifindex, state->dev->name,
-                          &state->im->mca_addr,
+                          &state->mc->mca_addr,
                           &psf->sf_addr,
                           psf->sf_count[MCAST_INCLUDE],
                           psf->sf_count[MCAST_EXCLUDE]);
-- 
2.17.1

Reply via email to