]> git.hungrycats.org Git - linux/commitdiff
sky2: allow multicast pause frames
authorStephen Hemminger <shemminger@linux-foundation.org>
Mon, 26 Feb 2007 00:51:40 +0000 (01:51 +0100)
committerAdrian Bunk <bunk@stusta.de>
Mon, 26 Feb 2007 00:51:40 +0000 (01:51 +0100)
The 802 standard allows pause frames to be either unicast or multicast.
Switches seem to send unicast frames, but on a direct link, other boards send
multicast pause.  Unless the filter bit is set, these pause frames get
dropped.

Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
drivers/net/sky2.c

index f0b1925931914754f839cdaea4fc5bfceac912ef..a173e377580389a945e5de825739e8b672a22a39 100644 (file)
@@ -2686,6 +2686,14 @@ static int sky2_set_mac_address(struct net_device *dev, void *p)
        return 0;
 }
 
+static void inline sky2_add_filter(u8 filter[8], const u8 *addr)
+{
+       u32 bit;
+
+       bit = ether_crc(ETH_ALEN, addr) & 63;
+       filter[bit >> 3] |= 1 << (bit & 7);
+}
+
 static void sky2_set_multicast(struct net_device *dev)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
@@ -2694,6 +2702,7 @@ static void sky2_set_multicast(struct net_device *dev)
        struct dev_mc_list *list = dev->mc_list;
        u16 reg;
        u8 filter[8];
+       static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 };
 
        memset(filter, 0, sizeof(filter));
 
@@ -2704,16 +2713,17 @@ static void sky2_set_multicast(struct net_device *dev)
                reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
        else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16)     /* all multicast */
                memset(filter, 0xff, sizeof(filter));
-       else if (dev->mc_count == 0)    /* no multicast */
+       else if (dev->mc_count == 0 && !sky2->rx_pause) /* no multicast */
                reg &= ~GM_RXCR_MCF_ENA;
        else {
                int i;
                reg |= GM_RXCR_MCF_ENA;
 
-               for (i = 0; list && i < dev->mc_count; i++, list = list->next) {
-                       u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
-                       filter[bit / 8] |= 1 << (bit % 8);
-               }
+               if (sky2->rx_pause)
+                       sky2_add_filter(filter, pause_mc_addr);
+
+               for (i = 0; list && i < dev->mc_count; i++, list = list->next)
+                       sky2_add_filter(filter, list->dmi_addr);
        }
 
        gma_write16(hw, port, GM_MC_ADDR_H1,