perf hist: fix objdump output parsing
[safe/jmp/linux-2.6] / net / atm / br2684.c
index 05fafdc..6719af6 100644 (file)
@@ -6,6 +6,8 @@
  *          Eric Kinzie, 2006-2007, US Naval Research Laboratory
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -15,7 +17,8 @@
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/ip.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
 #include <net/arp.h>
 #include <linux/atm.h>
 #include <linux/atmdev.h>
 
 #include "common.h"
 
-#ifdef SKB_DEBUG
 static void skb_debug(const struct sk_buff *skb)
 {
+#ifdef SKB_DEBUG
 #define NUM2PRINT 50
-       char buf[NUM2PRINT * 3 + 1];    /* 3 chars per byte */
-       int i = 0;
-       for (i = 0; i < skb->len && i < NUM2PRINT; i++) {
-               sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
-       }
-       printk(KERN_DEBUG "br2684: skb: %s\n", buf);
-}
-#else
-#define skb_debug(skb) do {} while (0)
+       print_hex_dump(KERN_DEBUG, "br2684: skb: ", DUMP_OFFSET,
+                      16, 1, skb->data, min(NUM2PRINT, skb->len), true);
 #endif
+}
 
 #define BR2684_ETHERTYPE_LEN   2
 #define BR2684_PAD_LEN         2
@@ -52,12 +49,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,
@@ -68,8 +65,8 @@ struct br2684_vcc {
        struct atm_vcc *atmvcc;
        struct net_device *device;
        /* keep old push, pop functions for chaining */
-       void (*old_push) (struct atm_vcc * vcc, struct sk_buff * skb);
-       /* void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb); */
+       void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb);
+       void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
        enum br2684_encaps encaps;
        struct list_head brvccs;
 #ifdef CONFIG_ATM_BR2684_IPFILTER
@@ -83,7 +80,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 +97,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)
@@ -143,14 +139,31 @@ static struct net_device *br2684_find_dev(const struct br2684_if_spec *s)
        return NULL;
 }
 
+/* chained vcc->pop function.  Check if we should wake the netif_queue */
+static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
+{
+       struct br2684_vcc *brvcc = BR2684_VCC(vcc);
+       struct net_device *net_dev = skb->dev;
+
+       pr_debug("(vcc %p ; net_dev %p )\n", vcc, net_dev);
+       brvcc->old_pop(vcc, skb);
+
+       if (!net_dev)
+               return;
+
+       if (atm_may_send(vcc, 0))
+               netif_wake_queue(net_dev);
+
+}
 /*
  * Send a packet out a particular vcc.  Not to useful right now, but paves
  * 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;
 
@@ -200,47 +213,47 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
 
        ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
        pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
-       if (!atm_may_send(atmvcc, skb->truesize)) {
-               /*
-                * We free this here for now, because we cannot know in a higher
-                * layer whether the skb pointer it supplied wasn't freed yet.
-                * Now, it always is.
-                */
-               dev_kfree_skb(skb);
-               return 0;
-       }
        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);
+
+       if (!atm_may_send(atmvcc, 0)) {
+               netif_stop_queue(brvcc->device);
+               /*check for race with br2684_pop*/
+               if (atm_may_send(atmvcc, 0))
+                       netif_start_queue(brvcc->device);
+       }
+
        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 */
 }
 
-static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
+                                    struct net_device *dev)
 {
        struct br2684_dev *brdev = BRPRIV(dev);
        struct br2684_vcc *brvcc;
 
-       pr_debug("br2684_start_xmit, skb->dst=%p\n", skb->dst);
+       pr_debug("skb_dst(skb)=%p\n", skb_dst(skb));
        read_lock(&devs_lock);
        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;
+               return NETDEV_TX_OK;
        }
-       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
@@ -248,27 +261,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;
+       return NETDEV_TX_OK;
 }
 
 /*
  * 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;
@@ -291,7 +297,8 @@ static int br2684_setfilt(struct atm_vcc *atmvcc, void __user * arg)
                struct br2684_dev *brdev;
                read_lock(&devs_lock);
                brdev = BRPRIV(br2684_find_dev(&fs.ifspec));
-               if (brdev == NULL || list_empty(&brdev->brvccs) || brdev->brvccs.next != brdev->brvccs.prev)    /* >1 VCC */
+               if (brdev == NULL || list_empty(&brdev->brvccs) ||
+                   brdev->brvccs.next != brdev->brvccs.prev)   /* >1 VCC */
                        brvcc = NULL;
                else
                        brvcc = list_entry_brvcc(brdev->brvccs.next);
@@ -343,7 +350,7 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
        struct net_device *net_dev = brvcc->device;
        struct br2684_dev *brdev = BRPRIV(net_dev);
 
-       pr_debug("br2684_push\n");
+       pr_debug("\n");
 
        if (unlikely(skb == NULL)) {
                /* skb==NULL means VCC is being destroyed */
@@ -367,29 +374,25 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
                        __skb_trim(skb, skb->len - 4);
 
                /* accept packets that have "ipv[46]" in the snap header */
-               if ((skb->len >= (sizeof(llc_oui_ipv4)))
-                   &&
-                   (memcmp
-                    (skb->data, llc_oui_ipv4,
-                     sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) {
-                       if (memcmp
-                           (skb->data + 6, ethertype_ipv6,
-                            sizeof(ethertype_ipv6)) == 0)
-                               skb->protocol = __constant_htons(ETH_P_IPV6);
-                       else if (memcmp
-                                (skb->data + 6, ethertype_ipv4,
-                                 sizeof(ethertype_ipv4)) == 0)
-                               skb->protocol = __constant_htons(ETH_P_IP);
+               if ((skb->len >= (sizeof(llc_oui_ipv4))) &&
+                   (memcmp(skb->data, llc_oui_ipv4,
+                           sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) {
+                       if (memcmp(skb->data + 6, ethertype_ipv6,
+                                  sizeof(ethertype_ipv6)) == 0)
+                               skb->protocol = htons(ETH_P_IPV6);
+                       else if (memcmp(skb->data + 6, ethertype_ipv4,
+                                       sizeof(ethertype_ipv4)) == 0)
+                               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;
-                       /*
-                        * Let us waste some time for checking the encapsulation.
-                        * Note, that only 7 char is checked so frames with a valid FCS
-                        * are also accepted (but FCS is not checked of course).
-                        */
+               /*
+                * Let us waste some time for checking the encapsulation.
+                * Note, that only 7 char is checked so frames with a valid FCS
+                * are also accepted (but FCS is not checked of course).
+                */
                } else if ((skb->len >= sizeof(llc_oui_pid_pad)) &&
                           (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) {
                        skb_pull(skb, sizeof(llc_oui_pid_pad));
@@ -404,9 +407,9 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
                        skb_reset_network_header(skb);
                        iph = ip_hdr(skb);
                        if (iph->version == 4)
-                               skb->protocol = __constant_htons(ETH_P_IP);
+                               skb->protocol = htons(ETH_P_IP);
                        else if (iph->version == 6)
-                               skb->protocol = __constant_htons(ETH_P_IPV6);
+                               skb->protocol = htons(ETH_P_IPV6);
                        else
                                goto error;
                        skb->pkt_type = PACKET_HOST;
@@ -430,20 +433,19 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
        /* sigh, interface is down? */
        if (unlikely(!(net_dev->flags & IFF_UP)))
                goto dropped;
-       brdev->stats.rx_packets++;
-       brdev->stats.rx_bytes += skb->len;
+       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:
-       brdev->stats.rx_dropped++;
+       net_dev->stats.rx_dropped++;
        goto free_skb;
 error:
-       brdev->stats.rx_errors++;
+       net_dev->stats.rx_errors++;
 free_skb:
        dev_kfree_skb(skb);
-       return;
 }
 
 /*
@@ -452,9 +454,10 @@ free_skb:
  */
 static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
 {
+       struct sk_buff_head queue;
        int err;
        struct br2684_vcc *brvcc;
-       struct sk_buff *skb;
+       struct sk_buff *skb, *tmp;
        struct sk_buff_head *rq;
        struct br2684_dev *brdev;
        struct net_device *net_dev;
@@ -469,8 +472,7 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
        write_lock_irq(&devs_lock);
        net_dev = br2684_find_dev(&be.ifspec);
        if (net_dev == NULL) {
-               printk(KERN_ERR
-                      "br2684: tried to attach to non-existant device\n");
+               pr_err("tried to attach to non-existant device\n");
                err = -ENXIO;
                goto error;
        }
@@ -484,17 +486,16 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
                err = -EEXIST;
                goto error;
        }
-       if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO ||
-           be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps !=
-                                                              BR2684_ENCAPS_VC
-                                                              && be.encaps !=
-                                                              BR2684_ENCAPS_LLC)
-           || be.min_size != 0) {
+       if (be.fcs_in != BR2684_FCSIN_NO ||
+           be.fcs_out != BR2684_FCSOUT_NO ||
+           be.fcs_auto || be.has_vpiid || be.send_padding ||
+           (be.encaps != BR2684_ENCAPS_VC &&
+            be.encaps != BR2684_ENCAPS_LLC) ||
+           be.min_size != 0) {
                err = -EINVAL;
                goto error;
        }
-       pr_debug("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc,
-                be.encaps, brvcc);
+       pr_debug("vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps, brvcc);
        if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) {
                unsigned char *esi = atmvcc->dev->esi;
                if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5])
@@ -509,41 +510,48 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
        atmvcc->user_back = brvcc;
        brvcc->encaps = (enum br2684_encaps)be.encaps;
        brvcc->old_push = atmvcc->push;
+       brvcc->old_pop = atmvcc->pop;
        barrier();
        atmvcc->push = br2684_push;
+       atmvcc->pop = br2684_pop;
 
+       __skb_queue_head_init(&queue);
        rq = &sk_atm(atmvcc)->sk_receive_queue;
 
        spin_lock_irqsave(&rq->lock, flags);
-       if (skb_queue_empty(rq)) {
-               skb = NULL;
-       } else {
-               /* NULL terminate the list.  */
-               rq->prev->next = NULL;
-               skb = rq->next;
-       }
-       rq->prev = rq->next = (struct sk_buff *)rq;
-       rq->qlen = 0;
+       skb_queue_splice_init(rq, &queue);
        spin_unlock_irqrestore(&rq->lock, flags);
 
-       while (skb) {
-               struct sk_buff *next = skb->next;
+       skb_queue_walk_safe(&queue, skb, tmp) {
+               struct net_device *dev = skb->dev;
 
-               skb->next = skb->prev = NULL;
-               br2684_push(atmvcc, skb);
-               BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
-               BRPRIV(skb->dev)->stats.rx_packets--;
+               dev->stats.rx_bytes -= skb->len;
+               dev->stats.rx_packets--;
 
-               skb = next;
+               br2684_push(atmvcc, skb);
        }
        __module_get(THIS_MODULE);
        return 0;
-      error:
+
+error:
        write_unlock_irq(&devs_lock);
        kfree(brvcc);
        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 const struct net_device_ops br2684_netdev_ops_routed = {
+       .ndo_start_xmit         = br2684_start_xmit,
+       .ndo_set_mac_address    = br2684_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu
+};
+
 static void br2684_setup(struct net_device *netdev)
 {
        struct br2684_dev *brdev = BRPRIV(netdev);
@@ -551,10 +559,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);
 }
@@ -562,13 +567,10 @@ static void br2684_setup(struct net_device *netdev)
 static void br2684_setup_routed(struct net_device *netdev)
 {
        struct br2684_dev *brdev = BRPRIV(netdev);
-       brdev->net_dev = 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_routed;
        netdev->addr_len = 0;
        netdev->mtu = 1500;
        netdev->type = ARPHRD_PPP;
@@ -577,7 +579,7 @@ static void br2684_setup_routed(struct net_device *netdev)
        INIT_LIST_HEAD(&brdev->brvccs);
 }
 
-static int br2684_create(void __user * arg)
+static int br2684_create(void __user *arg)
 {
        int err;
        struct net_device *netdev;
@@ -585,11 +587,10 @@ static int br2684_create(void __user * arg)
        struct atm_newif_br2684 ni;
        enum br2684_payload payload;
 
-       pr_debug("br2684_create\n");
+       pr_debug("\n");
 
-       if (copy_from_user(&ni, arg, sizeof ni)) {
+       if (copy_from_user(&ni, arg, sizeof ni))
                return -EFAULT;
-       }
 
        if (ni.media & BR2684_FLAG_ROUTED)
                payload = p_routed;
@@ -597,9 +598,8 @@ static int br2684_create(void __user * arg)
                payload = p_bridged;
        ni.media &= 0xffff;     /* strip flags */
 
-       if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) {
+       if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500)
                return -EINVAL;
-       }
 
        netdev = alloc_netdev(sizeof(struct br2684_dev),
                              ni.ifname[0] ? ni.ifname : "nas%d",
@@ -614,7 +614,7 @@ static int br2684_create(void __user * arg)
        /* open, stop, do_ioctl ? */
        err = register_netdev(netdev);
        if (err < 0) {
-               printk(KERN_ERR "br2684_create: register_netdev failed\n");
+               pr_err("register_netdev failed\n");
                free_netdev(netdev);
                return err;
        }
@@ -698,12 +698,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) {