mac80211: Cancel the power save timer in ieee80211_stop.
[safe/jmp/linux-2.6] / net / ethernet / eth.c
index ed8a3d4..280352a 100644 (file)
@@ -57,6 +57,7 @@
 #include <net/sock.h>
 #include <net/ipv6.h>
 #include <net/ip.h>
+#include <net/dsa.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
@@ -129,7 +130,7 @@ int eth_rebuild_header(struct sk_buff *skb)
 
        switch (eth->h_proto) {
 #ifdef CONFIG_INET
-       case __constant_htons(ETH_P_IP):
+       case htons(ETH_P_IP):
                return arp_find(eth->h_dest, skb);
 #endif
        default:
@@ -164,8 +165,8 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
        skb_pull(skb, ETH_HLEN);
        eth = eth_hdr(skb);
 
-       if (is_multicast_ether_addr(eth->h_dest)) {
-               if (!compare_ether_addr(eth->h_dest, dev->broadcast))
+       if (unlikely(is_multicast_ether_addr(eth->h_dest))) {
+               if (!compare_ether_addr_64bits(eth->h_dest, dev->broadcast))
                        skb->pkt_type = PACKET_BROADCAST;
                else
                        skb->pkt_type = PACKET_MULTICAST;
@@ -180,10 +181,21 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
         */
 
        else if (1 /*dev->flags&IFF_PROMISC */ ) {
-               if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr)))
+               if (unlikely(compare_ether_addr_64bits(eth->h_dest, dev->dev_addr)))
                        skb->pkt_type = PACKET_OTHERHOST;
        }
 
+       /*
+        * Some variants of DSA tagging don't have an ethertype field
+        * at all, so we check here whether one of those tagging
+        * variants has been configured on the receiving interface,
+        * and if so, set skb->protocol without looking at the packet.
+        */
+       if (netdev_uses_dsa_tags(dev))
+               return htons(ETH_P_DSA);
+       if (netdev_uses_trailer_tags(dev))
+               return htons(ETH_P_TRAILER);
+
        if (ntohs(eth->h_proto) >= 1536)
                return eth->h_proto;
 
@@ -270,7 +282,7 @@ EXPORT_SYMBOL(eth_header_cache_update);
  * This doesn't change hardware matching, so needs to be overridden
  * for most real devices.
  */
-static int eth_mac_addr(struct net_device *dev, void *p)
+int eth_mac_addr(struct net_device *dev, void *p)
 {
        struct sockaddr *addr = p;
 
@@ -281,6 +293,7 @@ static int eth_mac_addr(struct net_device *dev, void *p)
        memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
        return 0;
 }
+EXPORT_SYMBOL(eth_mac_addr);
 
 /**
  * eth_change_mtu - set new MTU size
@@ -290,13 +303,23 @@ static int eth_mac_addr(struct net_device *dev, void *p)
  * Allow changing MTU size. Needs to be overridden for devices
  * supporting jumbo frames.
  */
-static int eth_change_mtu(struct net_device *dev, int new_mtu)
+int eth_change_mtu(struct net_device *dev, int new_mtu)
 {
        if (new_mtu < 68 || new_mtu > ETH_DATA_LEN)
                return -EINVAL;
        dev->mtu = new_mtu;
        return 0;
 }
+EXPORT_SYMBOL(eth_change_mtu);
+
+int eth_validate_addr(struct net_device *dev)
+{
+       if (!is_valid_ether_addr(dev->dev_addr))
+               return -EADDRNOTAVAIL;
+
+       return 0;
+}
+EXPORT_SYMBOL(eth_validate_addr);
 
 const struct header_ops eth_header_ops ____cacheline_aligned = {
        .create         = eth_header,
@@ -314,10 +337,11 @@ const struct header_ops eth_header_ops ____cacheline_aligned = {
 void ether_setup(struct net_device *dev)
 {
        dev->header_ops         = &eth_header_ops;
-
+#ifdef CONFIG_COMPAT_NET_DEV_OPS
        dev->change_mtu         = eth_change_mtu;
        dev->set_mac_address    = eth_mac_addr;
-
+       dev->validate_addr      = eth_validate_addr;
+#endif
        dev->type               = ARPHRD_ETHER;
        dev->hard_header_len    = ETH_HLEN;
        dev->mtu                = ETH_DATA_LEN;
@@ -350,10 +374,34 @@ struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count)
 }
 EXPORT_SYMBOL(alloc_etherdev_mq);
 
-char *print_mac(char *buf, const u8 *addr)
+static size_t _format_mac_addr(char *buf, int buflen,
+                               const unsigned char *addr, int len)
+{
+       int i;
+       char *cp = buf;
+
+       for (i = 0; i < len; i++) {
+               cp += scnprintf(cp, buflen - (cp - buf), "%02x", addr[i]);
+               if (i == len - 1)
+                       break;
+               cp += strlcpy(cp, ":", buflen - (cp - buf));
+       }
+       return cp - buf;
+}
+
+ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len)
+{
+       size_t l;
+
+       l = _format_mac_addr(buf, PAGE_SIZE, addr, len);
+       l += strlcpy(buf + l, "\n", PAGE_SIZE - l);
+       return ((ssize_t) l);
+}
+EXPORT_SYMBOL(sysfs_format_mac);
+
+char *print_mac(char *buf, const unsigned char *addr)
 {
-       sprintf(buf, MAC_FMT,
-               addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+       _format_mac_addr(buf, MAC_BUF_SIZE, addr, ETH_ALEN);
        return buf;
 }
 EXPORT_SYMBOL(print_mac);