Subject: [PATCH] br2684: restore net_dev initialization
[safe/jmp/linux-2.6] / net / atm / br2684.c
index 5c8a0dc..3100a89 100644 (file)
@@ -52,12 +52,12 @@ static void skb_debug(const struct sk_buff *skb)
 #define ETHERTYPE_IPV6 0x86, 0xdd
 #define PAD_BRIDGED    0x00, 0x00
 
-static unsigned char ethertype_ipv4[] = { ETHERTYPE_IPV4 };
-static unsigned char ethertype_ipv6[] = { ETHERTYPE_IPV6 };
-static unsigned char llc_oui_pid_pad[] =
+static const unsigned char ethertype_ipv4[] = { ETHERTYPE_IPV4 };
+static const unsigned char ethertype_ipv6[] = { ETHERTYPE_IPV6 };
+static const unsigned char llc_oui_pid_pad[] =
                        { LLC, SNAP_BRIDGED, PID_ETHERNET, PAD_BRIDGED };
-static unsigned char llc_oui_ipv4[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV4 };
-static unsigned char llc_oui_ipv6[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV6 };
+static const unsigned char llc_oui_ipv4[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV4 };
+static const unsigned char llc_oui_ipv6[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV6 };
 
 enum br2684_encaps {
        e_vc = BR2684_ENCAPS_VC,
@@ -83,7 +83,6 @@ struct br2684_dev {
        struct list_head br2684_devs;
        int number;
        struct list_head brvccs;        /* one device <=> one vcc (before xmas) */
-       struct net_device_stats stats;
        int mac_was_set;
        enum br2684_payload payload;
 };
@@ -101,7 +100,7 @@ static LIST_HEAD(br2684_devs);
 
 static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
 {
-       return (struct br2684_dev *)net_dev->priv;
+       return (struct br2684_dev *)netdev_priv(net_dev);
 }
 
 static inline struct net_device *list_entry_brdev(const struct list_head *le)
@@ -148,9 +147,10 @@ static struct net_device *br2684_find_dev(const struct br2684_if_spec *s)
  * the way for multiple vcc's per itf.  Returns true if we can send,
  * otherwise false
  */
-static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
+static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
                           struct br2684_vcc *brvcc)
 {
+       struct br2684_dev *brdev = BRPRIV(dev);
        struct atm_vcc *atmvcc;
        int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
 
@@ -188,10 +188,13 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
                                return 0;
                        }
                }
-       } else {
-               skb_push(skb, 2);
-               if (brdev->payload == p_bridged)
+       } else { /* e_vc */
+               if (brdev->payload == p_bridged) {
+                       skb_push(skb, 2);
                        memset(skb->data, 0, 2);
+               } else { /* p_routed */
+                       skb_pull(skb, ETH_HLEN);
+               }
        }
        skb_debug(skb);
 
@@ -208,14 +211,14 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
        }
        atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
        ATM_SKB(skb)->atm_options = atmvcc->atm_options;
-       brdev->stats.tx_packets++;
-       brdev->stats.tx_bytes += skb->len;
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes += skb->len;
        atmvcc->send(atmvcc, skb);
        return 1;
 }
 
-static inline struct br2684_vcc *pick_outgoing_vcc(struct sk_buff *skb,
-                                                  struct br2684_dev *brdev)
+static inline struct br2684_vcc *pick_outgoing_vcc(const struct sk_buff *skb,
+                                                  const struct br2684_dev *brdev)
 {
        return list_empty(&brdev->brvccs) ? NULL : list_entry_brvcc(brdev->brvccs.next);        /* 1 vcc/dev right now */
 }
@@ -230,14 +233,14 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
        brvcc = pick_outgoing_vcc(skb, brdev);
        if (brvcc == NULL) {
                pr_debug("no vcc attached to dev %s\n", dev->name);
-               brdev->stats.tx_errors++;
-               brdev->stats.tx_carrier_errors++;
+               dev->stats.tx_errors++;
+               dev->stats.tx_carrier_errors++;
                /* netif_stop_queue(dev); */
                dev_kfree_skb(skb);
                read_unlock(&devs_lock);
                return 0;
        }
-       if (!br2684_xmit_vcc(skb, brdev, brvcc)) {
+       if (!br2684_xmit_vcc(skb, dev, brvcc)) {
                /*
                 * We should probably use netif_*_queue() here, but that
                 * involves added complication.  We need to walk before
@@ -245,27 +248,20 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
                 *
                 * Don't free here! this pointer might be no longer valid!
                 */
-               brdev->stats.tx_errors++;
-               brdev->stats.tx_fifo_errors++;
+               dev->stats.tx_errors++;
+               dev->stats.tx_fifo_errors++;
        }
        read_unlock(&devs_lock);
        return 0;
 }
 
-static struct net_device_stats *br2684_get_stats(struct net_device *dev)
-{
-       pr_debug("br2684_get_stats\n");
-       return &BRPRIV(dev)->stats;
-}
-
 /*
  * We remember when the MAC gets set, so we don't override it later with
  * the ESI of the ATM card of the first VC
  */
-static int (*my_eth_mac_addr) (struct net_device *, void *);
 static int br2684_mac_addr(struct net_device *dev, void *p)
 {
-       int err = my_eth_mac_addr(dev, p);
+       int err = eth_mac_addr(dev, p);
        if (!err)
                BRPRIV(dev)->mac_was_set = 1;
        return err;
@@ -346,9 +342,9 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
                /* skb==NULL means VCC is being destroyed */
                br2684_close_vcc(brvcc);
                if (list_empty(&brdev->brvccs)) {
-                       read_lock(&devs_lock);
+                       write_lock_irq(&devs_lock);
                        list_del(&brdev->br2684_devs);
-                       read_unlock(&devs_lock);
+                       write_unlock_irq(&devs_lock);
                        unregister_netdev(net_dev);
                        free_netdev(net_dev);
                }
@@ -372,16 +368,13 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
                        if (memcmp
                            (skb->data + 6, ethertype_ipv6,
                             sizeof(ethertype_ipv6)) == 0)
-                               skb->protocol = __constant_htons(ETH_P_IPV6);
+                               skb->protocol = htons(ETH_P_IPV6);
                        else if (memcmp
                                 (skb->data + 6, ethertype_ipv4,
                                  sizeof(ethertype_ipv4)) == 0)
-                               skb->protocol = __constant_htons(ETH_P_IP);
-                       else {
-                               brdev->stats.rx_errors++;
-                               dev_kfree_skb(skb);
-                               return;
-                       }
+                               skb->protocol = htons(ETH_P_IP);
+                       else
+                               goto error;
                        skb_pull(skb, sizeof(llc_oui_ipv4));
                        skb_reset_network_header(skb);
                        skb->pkt_type = PACKET_HOST;
@@ -394,44 +387,56 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
                           (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) {
                        skb_pull(skb, sizeof(llc_oui_pid_pad));
                        skb->protocol = eth_type_trans(skb, net_dev);
-               } else {
-                       brdev->stats.rx_errors++;
-                       dev_kfree_skb(skb);
-                       return;
-               }
+               } else
+                       goto error;
 
-       } else {
-               /* first 2 chars should be 0 */
-               if (*((u16 *) (skb->data)) != 0) {
-                       brdev->stats.rx_errors++;
-                       dev_kfree_skb(skb);
-                       return;
+       } else { /* e_vc */
+               if (brdev->payload == p_routed) {
+                       struct iphdr *iph;
+
+                       skb_reset_network_header(skb);
+                       iph = ip_hdr(skb);
+                       if (iph->version == 4)
+                               skb->protocol = htons(ETH_P_IP);
+                       else if (iph->version == 6)
+                               skb->protocol = htons(ETH_P_IPV6);
+                       else
+                               goto error;
+                       skb->pkt_type = PACKET_HOST;
+               } else { /* p_bridged */
+                       /* first 2 chars should be 0 */
+                       if (*((u16 *) (skb->data)) != 0)
+                               goto error;
+                       skb_pull(skb, BR2684_PAD_LEN);
+                       skb->protocol = eth_type_trans(skb, net_dev);
                }
-               skb_pull(skb, BR2684_PAD_LEN + ETH_HLEN);       /* pad, dstmac, srcmac, ethtype */
-               skb->protocol = eth_type_trans(skb, net_dev);
        }
 
 #ifdef CONFIG_ATM_BR2684_IPFILTER
-       if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) {
-               brdev->stats.rx_dropped++;
-               dev_kfree_skb(skb);
-               return;
-       }
+       if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb)))
+               goto dropped;
 #endif /* CONFIG_ATM_BR2684_IPFILTER */
        skb->dev = net_dev;
        ATM_SKB(skb)->vcc = atmvcc;     /* needed ? */
        pr_debug("received packet's protocol: %x\n", ntohs(skb->protocol));
        skb_debug(skb);
-       if (unlikely(!(net_dev->flags & IFF_UP))) {
-               /* sigh, interface is down */
-               brdev->stats.rx_dropped++;
-               dev_kfree_skb(skb);
-               return;
-       }
-       brdev->stats.rx_packets++;
-       brdev->stats.rx_bytes += skb->len;
+       /* sigh, interface is down? */
+       if (unlikely(!(net_dev->flags & IFF_UP)))
+               goto dropped;
+       net_dev->stats.rx_packets++;
+       net_dev->stats.rx_bytes += skb->len;
        memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
        netif_rx(skb);
+       return;
+
+dropped:
+       net_dev->stats.rx_dropped++;
+       goto free_skb;
+error:
+       net_dev->stats.rx_errors++;
+free_skb:
+       dev_kfree_skb(skb);
+       return;
 }
 
 /*
@@ -518,9 +523,9 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
                struct sk_buff *next = skb->next;
 
                skb->next = skb->prev = NULL;
-               BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
-               BRPRIV(skb->dev)->stats.rx_packets--;
                br2684_push(atmvcc, skb);
+               skb->dev->stats.rx_bytes -= skb->len;
+               skb->dev->stats.rx_packets--;
 
                skb = next;
        }
@@ -532,6 +537,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
        return err;
 }
 
+static const struct net_device_ops br2684_netdev_ops = {
+       .ndo_start_xmit         = br2684_start_xmit,
+       .ndo_set_mac_address    = br2684_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
 static void br2684_setup(struct net_device *netdev)
 {
        struct br2684_dev *brdev = BRPRIV(netdev);
@@ -539,10 +551,7 @@ static void br2684_setup(struct net_device *netdev)
        ether_setup(netdev);
        brdev->net_dev = netdev;
 
-       my_eth_mac_addr = netdev->set_mac_address;
-       netdev->set_mac_address = br2684_mac_addr;
-       netdev->hard_start_xmit = br2684_start_xmit;
-       netdev->get_stats = br2684_get_stats;
+       netdev->netdev_ops = &br2684_netdev_ops;
 
        INIT_LIST_HEAD(&brdev->brvccs);
 }
@@ -553,10 +562,8 @@ static void br2684_setup_routed(struct net_device *netdev)
        brdev->net_dev = netdev;
 
        netdev->hard_header_len = 0;
-       my_eth_mac_addr = netdev->set_mac_address;
-       netdev->set_mac_address = br2684_mac_addr;
-       netdev->hard_start_xmit = br2684_start_xmit;
-       netdev->get_stats = br2684_get_stats;
+
+       netdev->netdev_ops = &br2684_netdev_ops;
        netdev->addr_len = 0;
        netdev->mtu = 1500;
        netdev->type = ARPHRD_PPP;
@@ -663,6 +670,7 @@ static struct atm_ioctl br2684_ioctl_ops = {
 
 #ifdef CONFIG_PROC_FS
 static void *br2684_seq_start(struct seq_file *seq, loff_t * pos)
+       __acquires(devs_lock)
 {
        read_lock(&devs_lock);
        return seq_list_start(&br2684_devs, *pos);
@@ -674,6 +682,7 @@ static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t * pos)
 }
 
 static void br2684_seq_stop(struct seq_file *seq, void *v)
+       __releases(devs_lock)
 {
        read_unlock(&devs_lock);
 }
@@ -684,12 +693,11 @@ static int br2684_seq_show(struct seq_file *seq, void *v)
                                                    br2684_devs);
        const struct net_device *net_dev = brdev->net_dev;
        const struct br2684_vcc *brvcc;
-       DECLARE_MAC_BUF(mac);
 
-       seq_printf(seq, "dev %.16s: num=%d, mac=%s (%s)\n",
+       seq_printf(seq, "dev %.16s: num=%d, mac=%pM (%s)\n",
                   net_dev->name,
                   brdev->number,
-                  print_mac(mac, net_dev->dev_addr),
+                  net_dev->dev_addr,
                   brdev->mac_was_set ? "set" : "auto");
 
        list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {
@@ -740,9 +748,9 @@ static int __init br2684_init(void)
 {
 #ifdef CONFIG_PROC_FS
        struct proc_dir_entry *p;
-       if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
+       p = proc_create("br2684", 0, atm_proc_root, &br2684_proc_ops);
+       if (p == NULL)
                return -ENOMEM;
-       p->proc_fops = &br2684_proc_ops;
 #endif
        register_atm_ioctl(&br2684_ioctl_ops);
        return 0;