Ticket #6818: 0001-Separate-multicast-configuration-for-mesh-and-wlan-i.patch

File 0001-Separate-multicast-configuration-for-mesh-and-wlan-i.patch, 9.5 KB (added by jcardona, 6 years ago)
  • drivers/net/wireless/libertas/cmd.c

    From 97afdc602d96bf84afa083c6ddd2834e7628573a Mon Sep 17 00:00:00 2001
    From: Javier Cardona <javier@cozybit.com>
    Date: Fri, 2 May 2008 16:35:52 -0700
    Subject: [PATCH] Separate multicast configuration for mesh and wlan interfaces.
    
    Each device maintains its own list of bound multicast addresses.  Those lists
    are merged and purged from duplicate addresses before being sent to firmware.
    The maximum number of multicast addresses per virtual device has been cut in
    half to ensure that the merged list can be accommodated by the hardware.
    
    Also, configuration flags are ORed before being sent to firmware, which
    appears to be the least conflicting way of combining two virtual operating
    modes into a single wireless device.
    
    Based on patches from Ashish Shukla and David Woodhouse.
    
    Signed-off-by: Javier Cardona <javier@cozybit.com>
    ---
     drivers/net/wireless/libertas/cmd.c  |   58 ++++++++++++++++++--
     drivers/net/wireless/libertas/defs.h |    2 +
     drivers/net/wireless/libertas/dev.h  |    9 +++-
     drivers/net/wireless/libertas/main.c |  100 +++++++++++++++++++---------------
     4 files changed, 117 insertions(+), 52 deletions(-)
    
    diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
    index 0ae9851..a3cb4bd 100644
    a b static int lbs_cmd_mac_multicast_adr(struct lbs_private *priv, 
    814814                                      u16 cmd_action) 
    815815{ 
    816816        struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr; 
     817        u8 *mc_list_ptr = pMCastAdr->maclist; 
     818        u32 mc_count = 0, i, j, m, w; 
     819        DECLARE_MAC_BUF(mac); 
     820        int mesh_nr_mcastaddr, wlan_nr_mcastaddr; 
    817821 
    818822        lbs_deb_enter(LBS_DEB_CMD); 
    819823        cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) + 
    820824                             S_DS_GEN); 
    821825        cmd->command = cpu_to_le16(CMD_MAC_MULTICAST_ADR); 
    822  
    823         lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs); 
    824826        pMCastAdr->action = cpu_to_le16(cmd_action); 
    825         pMCastAdr->nr_of_adrs = 
    826             cpu_to_le16((u16) priv->nr_of_multicastmacaddr); 
    827         memcpy(pMCastAdr->maclist, priv->multicastlist, 
    828                priv->nr_of_multicastmacaddr * ETH_ALEN); 
    829827 
     828        /* There are two multicast address lists in priv.  Combine them into 
     829         * one before sending to firmware. 
     830         */ 
     831        m = MESH_MCAST_FILTER; 
     832        w = WLAN_MCAST_FILTER; 
     833 
     834        /* Only include addresses for interfaces that are up */ 
     835        wlan_nr_mcastaddr = (priv->dev->flags & IFF_UP) ? 
     836                priv->nr_of_multicastmacaddr[w] : 0; 
     837 
     838        mesh_nr_mcastaddr = 
     839                (priv->mesh_dev && priv->mesh_dev->flags & IFF_UP) ? 
     840                priv->nr_of_multicastmacaddr[m] : 0; 
     841 
     842        for (i = 0; i < wlan_nr_mcastaddr; i++) { 
     843                /* Skip duplicate address */ 
     844                int found = 0; 
     845                char *maddr = (char *)&priv->multicastlist[w][i]; 
     846 
     847                for (j = 0; j < mesh_nr_mcastaddr; j++) { 
     848                        if (!memcmp(maddr, priv->multicastlist[m][j], 
     849                                                ETH_ALEN)) { 
     850                                found = 1; 
     851                                break; 
     852                        } 
     853                } 
     854                if (!found) { 
     855                        memcpy(mc_list_ptr, maddr, ETH_ALEN); 
     856                        lbs_deb_cmd("MULTICAST_ADR: %s added to mcast filter\n", 
     857                                print_mac(mac, maddr)); 
     858                        mc_list_ptr += ETH_ALEN; 
     859                        mc_count++; 
     860                } 
     861        } 
     862 
     863        /* Copy rest of the list */ 
     864        for (j = 0; j < mesh_nr_mcastaddr; j++) { 
     865                memcpy(mc_list_ptr, priv->multicastlist[m][j], ETH_ALEN); 
     866                lbs_deb_cmd("MULTICAST_ADR: %s added to mcast filter\n", 
     867                        print_mac(mac, priv->multicastlist[m][j])); 
     868                mc_list_ptr += ETH_ALEN; 
     869                mc_count++; 
     870        } 
     871 
     872        pMCastAdr->nr_of_adrs = cpu_to_le16((u16)mc_count); 
     873        lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", 
     874                        pMCastAdr->nr_of_adrs); 
    830875        lbs_deb_leave(LBS_DEB_CMD); 
    831876        return 0; 
     877 
    832878} 
    833879 
    834880/** 
  • drivers/net/wireless/libertas/defs.h

    diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
    index 3053cc2..71ecb4c 100644
    a b static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in 
    126126*       station firmware to store Rx packet information. 
    127127* 
    128128*       Current version of MAC has a 32x6 multicast address buffer. 
     129*       The driver maintains separate multicast address lists for mesh and 
     130*       wlan interfaces, each one of size MRVDRV_MAX_MULTICAST_LIST_SIZE/2. 
    129131* 
    130132*       802.11b can have up to  14 channels, the driver keeps the 
    131133*       BSSID(MAC address) of each APs or Ad hoc stations it has sensed. 
  • drivers/net/wireless/libertas/dev.h

    diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
    index 1c6ec4d..03e018e 100644
    a b struct lbs_private { 
    230230 
    231231        /** MAC address information */ 
    232232        u8 current_addr[ETH_ALEN]; 
    233         u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; 
    234         u32 nr_of_multicastmacaddr; 
     233 
     234        /* Per virtual interface multicast settings */ 
     235#define WLAN_MCAST_FILTER 0 
     236#define MESH_MCAST_FILTER 1 
     237        u8 multicastlist[2][MRVDRV_MAX_MULTICAST_LIST_SIZE/2][ETH_ALEN]; 
     238        u32 nr_of_multicastmacaddr[2]; 
     239        u16 packetfilter[2]; 
    235240 
    236241        /** 802.11 statistics */ 
    237242//      struct cmd_DS_802_11_GET_STAT wlan802_11Stat; 
  • drivers/net/wireless/libertas/main.c

    diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
    index e012d08..f666cf2 100644
    a b done: 
    556556        return ret; 
    557557} 
    558558 
    559 static int lbs_copy_multicast_address(struct lbs_private *priv, 
    560                                      struct net_device *dev) 
     559static int lbs_copy_multicast_address(u8 (*mcast_list)[ETH_ALEN], 
     560                struct net_device *dev) 
    561561{ 
    562         int i = 0; 
     562        int i; 
    563563        struct dev_mc_list *mcptr = dev->mc_list; 
     564        DECLARE_MAC_BUF(mac); 
    564565 
    565566        for (i = 0; i < dev->mc_count; i++) { 
    566                 memcpy(&priv->multicastlist[i], mcptr->dmi_addr, ETH_ALEN); 
     567                memcpy(*mcast_list, mcptr->dmi_addr, ETH_ALEN); 
     568                lbs_deb_net("mcast address %s added to per-if filter\n", 
     569                        print_mac(mac, mcptr->dmi_addr)); 
    567570                mcptr = mcptr->next; 
     571                mcast_list++; 
    568572        } 
    569  
    570573        return i; 
    571  
    572574} 
    573575 
    574 static void lbs_set_multicast_list(struct net_device *dev) 
     576static void lbs_set_if_multicast_list(struct net_device *dev) 
    575577{ 
    576578        struct lbs_private *priv = dev->priv; 
    577         int oldpacketfilter; 
    578         DECLARE_MAC_BUF(mac); 
     579        char *iftyp; 
     580        int i; 
    579581 
    580582        lbs_deb_enter(LBS_DEB_NET); 
    581583 
    582         oldpacketfilter = priv->currentpacketfilter; 
     584        i = (priv->mesh_dev == dev) ? MESH_MCAST_FILTER : WLAN_MCAST_FILTER; 
     585        iftyp = (i == MESH_MCAST_FILTER) ? "mesh" : "wlan"; 
    583586 
    584587        if (dev->flags & IFF_PROMISC) { 
    585                 lbs_deb_net("enable promiscuous mode\n"); 
    586                 priv->currentpacketfilter |= 
     588                lbs_deb_net("enable promiscuous mode on %s if\n", iftyp); 
     589                priv->packetfilter[i] |= 
    587590                    CMD_ACT_MAC_PROMISCUOUS_ENABLE; 
    588                 priv->currentpacketfilter &= 
     591                priv->packetfilter[i] &= 
    589592                    ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | 
    590593                      CMD_ACT_MAC_MULTICAST_ENABLE); 
    591594        } else { 
    592595                /* Multicast */ 
    593                 priv->currentpacketfilter &= 
     596                priv->packetfilter[i] &= 
    594597                    ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; 
    595598 
    596599                if (dev->flags & IFF_ALLMULTI || dev->mc_count > 
    597                     MRVDRV_MAX_MULTICAST_LIST_SIZE) { 
    598                         lbs_deb_net( "enabling all multicast\n"); 
    599                         priv->currentpacketfilter |= 
     600                    MRVDRV_MAX_MULTICAST_LIST_SIZE/2) { 
     601                        lbs_deb_net("enable allmulti mode on %s if\n", iftyp); 
     602                        priv->packetfilter[i] |= 
    600603                            CMD_ACT_MAC_ALL_MULTICAST_ENABLE; 
    601                         priv->currentpacketfilter &= 
     604                        priv->packetfilter[i] &= 
    602605                            ~CMD_ACT_MAC_MULTICAST_ENABLE; 
    603606                } else { 
    604                         priv->currentpacketfilter &= 
     607                        priv->packetfilter[i] &= 
    605608                            ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; 
    606609 
    607610                        if (!dev->mc_count) { 
    608                                 lbs_deb_net("no multicast addresses, " 
    609                                        "disabling multicast\n"); 
    610                                 priv->currentpacketfilter &= 
    611                                     ~CMD_ACT_MAC_MULTICAST_ENABLE; 
     611                                priv->nr_of_multicastmacaddr[i] = 0; 
     612                                lbs_deb_net("no mcast on %s if\n", iftyp); 
     613                                priv->packetfilter[i] &= 
     614                                        ~CMD_ACT_MAC_MULTICAST_ENABLE; 
    612615                        } else { 
    613                                 int i; 
    614  
    615                                 priv->currentpacketfilter |= 
     616                                priv->packetfilter[i] |= 
    616617                                    CMD_ACT_MAC_MULTICAST_ENABLE; 
    617618 
    618                                 priv->nr_of_multicastmacaddr = 
    619                                     lbs_copy_multicast_address(priv, dev); 
    620  
    621                                 lbs_deb_net("multicast addresses: %d\n", 
    622                                        dev->mc_count); 
    623  
    624                                 for (i = 0; i < dev->mc_count; i++) { 
    625                                         lbs_deb_net("Multicast address %d:%s\n", 
    626                                                i, print_mac(mac, 
    627                                                priv->multicastlist[i])); 
    628                                 } 
    629                                 /* send multicast addresses to firmware */ 
    630                                 lbs_prepare_and_send_command(priv, 
    631                                                       CMD_MAC_MULTICAST_ADR, 
    632                                                       CMD_ACT_SET, 0, 0, 
    633                                                       NULL); 
     619                                lbs_deb_net("mcast enable on %s if\n", iftyp); 
     620                                priv->nr_of_multicastmacaddr[i] = 
     621                                        lbs_copy_multicast_address( 
     622                                                priv->multicastlist[i], dev); 
    634623                        } 
    635624                } 
    636625        } 
    637626 
     627        lbs_deb_leave(LBS_DEB_NET); 
     628} 
     629 
     630static void lbs_set_multicast_list(struct net_device *dev) 
     631{ 
     632        struct lbs_private *priv = dev->priv; 
     633        int oldpacketfilter; 
     634 
     635        lbs_deb_enter(LBS_DEB_NET); 
     636 
     637        oldpacketfilter = priv->currentpacketfilter; 
     638 
     639        /* Update the multicast filter for this device. */ 
     640        lbs_set_if_multicast_list(dev); 
     641 
     642        /* Combine mcast flags from both devs before sending to firmware. */ 
     643        priv->currentpacketfilter = priv->packetfilter[MESH_MCAST_FILTER] | 
     644                priv->packetfilter[WLAN_MCAST_FILTER]; 
     645 
     646        if (priv->currentpacketfilter & CMD_ACT_MAC_MULTICAST_ENABLE) 
     647                lbs_prepare_and_send_command(priv, CMD_MAC_MULTICAST_ADR, 
     648                                CMD_ACT_SET, 0, 0, NULL); 
     649 
    638650        if (priv->currentpacketfilter != oldpacketfilter) { 
    639651                lbs_set_mac_packet_filter(priv); 
    640652        } 
    641  
    642         lbs_deb_leave(LBS_DEB_NET); 
    643653} 
    644654 
    645655/** 
    static int lbs_add_mesh(struct lbs_private *priv) 
    13161326#ifdef  WIRELESS_EXT 
    13171327        mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; 
    13181328#endif 
     1329        mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 
     1330        mesh_dev->set_multicast_list = lbs_set_multicast_list; 
    13191331        /* Register virtual mesh interface */ 
    13201332        ret = register_netdev(mesh_dev); 
    13211333        if (ret) {