[PKTGEN]: fix device name handling
[powerpc.git] / net / core / pktgen.c
index 74a9a32..895739f 100644 (file)
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/capability.h>
+#include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/list.h>
 
 #define VERSION  "pktgen v2.68: Packet Generator for packet performance testing.\n"
 
-/* #define PG_DEBUG(a) a */
-#define PG_DEBUG(a)
-
 /* The buckets are exponential in 'width' */
 #define LAT_BUCKETS_MAX 32
 #define IP_NAME_SZ 32
 #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */
-#define MPLS_STACK_BOTTOM __constant_htonl(0x00000100)
+#define MPLS_STACK_BOTTOM htonl(0x00000100)
 
 /* Device flag bits */
 #define F_IPSRC_RND   (1<<0)   /* IP-Src Random  */
@@ -213,15 +211,11 @@ struct flow_state {
 };
 
 struct pktgen_dev {
-
        /*
         * Try to keep frequent/infrequent used vars. separated.
         */
-
-       char ifname[IFNAMSIZ];
-       char result[512];
-
-       struct pktgen_thread *pg_thread;        /* the owner */
+       struct proc_dir_entry *entry;   /* proc file */
+       struct pktgen_thread *pg_thread;/* the owner */
        struct list_head list;          /* Used for chaining in the thread's run-queue */
 
        int running;            /* if this changes to false, the test will stop */
@@ -348,6 +342,8 @@ struct pktgen_dev {
        unsigned cflows;        /* Concurrent flows (config) */
        unsigned lflow;         /* Flow length  (config) */
        unsigned nflows;        /* accumulated flows (stats) */
+
+       char result[512];
 };
 
 struct pktgen_hdr {
@@ -467,17 +463,6 @@ static inline __u64 pg_div64(__u64 n, __u64 base)
        return tmp;
 }
 
-static inline u32 pktgen_random(void)
-{
-#if 0
-       __u32 n;
-       get_random_bytes(&n, 4);
-       return n;
-#else
-       return net_random();
-#endif
-}
-
 static inline __u64 getCurMs(void)
 {
        struct timeval tv;
@@ -511,7 +496,7 @@ static void pktgen_stop_all_threads_ifs(void);
 static int pktgen_stop_device(struct pktgen_dev *pkt_dev);
 static void pktgen_stop(struct pktgen_thread *t);
 static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
-static int pktgen_mark_device(const char *ifname);
+
 static unsigned int scan_ip6(const char *s, char ip[16]);
 static unsigned int fmt_ip6(char *s, const char ip[16]);
 
@@ -605,7 +590,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
                   "     frags: %d  delay: %u  clone_skb: %d  ifname: %s\n",
                   pkt_dev->nfrags,
                   1000 * pkt_dev->delay_us + pkt_dev->delay_ns,
-                  pkt_dev->clone_skb, pkt_dev->ifname);
+                  pkt_dev->clone_skb, pkt_dev->odev->name);
 
        seq_printf(seq, "     flows: %u flowlen: %u\n", pkt_dev->cflows,
                   pkt_dev->lflow);
@@ -1696,13 +1681,13 @@ static int pktgen_thread_show(struct seq_file *seq, void *v)
        if_lock(t);
        list_for_each_entry(pkt_dev, &t->if_list, list)
                if (pkt_dev->running)
-                       seq_printf(seq, "%s ", pkt_dev->ifname);
+                       seq_printf(seq, "%s ", pkt_dev->odev->name);
 
        seq_printf(seq, "\nStopped: ");
 
        list_for_each_entry(pkt_dev, &t->if_list, list)
                if (!pkt_dev->running)
-                       seq_printf(seq, "%s ", pkt_dev->ifname);
+                       seq_printf(seq, "%s ", pkt_dev->odev->name);
 
        if (t->result[0])
                seq_printf(seq, "\nResult: %s\n", t->result);
@@ -1848,16 +1833,14 @@ static struct pktgen_dev *__pktgen_NN_threads(const char *ifname, int remove)
 /*
  * mark a device for removal
  */
-static int pktgen_mark_device(const char *ifname)
+static void pktgen_mark_device(const char *ifname)
 {
        struct pktgen_dev *pkt_dev = NULL;
        const int max_tries = 10, msec_per_try = 125;
        int i = 0;
-       int ret = 0;
 
        mutex_lock(&pktgen_thread_lock);
-       PG_DEBUG(printk("pktgen: pktgen_mark_device marking %s for removal\n",
-                       ifname));
+       pr_debug("pktgen: pktgen_mark_device marking %s for removal\n", ifname);
 
        while (1) {
 
@@ -1866,8 +1849,8 @@ static int pktgen_mark_device(const char *ifname)
                        break;  /* success */
 
                mutex_unlock(&pktgen_thread_lock);
-               PG_DEBUG(printk("pktgen: pktgen_mark_device waiting for %s "
-                               "to disappear....\n", ifname));
+               pr_debug("pktgen: pktgen_mark_device waiting for %s "
+                               "to disappear....\n", ifname);
                schedule_timeout_interruptible(msecs_to_jiffies(msec_per_try));
                mutex_lock(&pktgen_thread_lock);
 
@@ -1875,32 +1858,49 @@ static int pktgen_mark_device(const char *ifname)
                        printk("pktgen_mark_device: timed out after waiting "
                               "%d msec for device %s to be removed\n",
                               msec_per_try * i, ifname);
-                       ret = 1;
                        break;
                }
 
        }
 
        mutex_unlock(&pktgen_thread_lock);
+}
 
-       return ret;
+static void pktgen_change_name(struct net_device *dev)
+{
+       struct pktgen_thread *t;
+
+       list_for_each_entry(t, &pktgen_threads, th_list) {
+               struct pktgen_dev *pkt_dev;
+
+               list_for_each_entry(pkt_dev, &t->if_list, list) {
+                       if (pkt_dev->odev != dev)
+                               continue;
+
+                       remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);
+
+                       pkt_dev->entry = create_proc_entry(dev->name, 0600,
+                                                          pg_proc_dir);
+                       if (!pkt_dev->entry)
+                               printk(KERN_ERR "pktgen: can't move proc "
+                                      " entry for '%s'\n", dev->name);
+                       break;
+               }
+       }
 }
 
 static int pktgen_device_event(struct notifier_block *unused,
                               unsigned long event, void *ptr)
 {
-       struct net_device *dev = (struct net_device *)(ptr);
+       struct net_device *dev = ptr;
 
        /* It is OK that we do not hold the group lock right now,
         * as we run under the RTNL lock.
         */
 
        switch (event) {
-       case NETDEV_CHANGEADDR:
-       case NETDEV_GOING_DOWN:
-       case NETDEV_DOWN:
-       case NETDEV_UP:
-               /* Ignore for now */
+       case NETDEV_CHANGENAME:
+               pktgen_change_name(dev);
                break;
 
        case NETDEV_UNREGISTER:
@@ -1913,41 +1913,36 @@ static int pktgen_device_event(struct notifier_block *unused,
 
 /* Associate pktgen_dev with a device. */
 
-static struct net_device *pktgen_setup_dev(struct pktgen_dev *pkt_dev)
+static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname)
 {
        struct net_device *odev;
+       int err;
 
        /* Clean old setups */
-
        if (pkt_dev->odev) {
                dev_put(pkt_dev->odev);
                pkt_dev->odev = NULL;
        }
 
-       odev = dev_get_by_name(pkt_dev->ifname);
-
+       odev = dev_get_by_name(ifname);
        if (!odev) {
-               printk("pktgen: no such netdevice: \"%s\"\n", pkt_dev->ifname);
-               goto out;
+               printk("pktgen: no such netdevice: \"%s\"\n", ifname);
+               return -ENODEV;
        }
+
        if (odev->type != ARPHRD_ETHER) {
-               printk("pktgen: not an ethernet device: \"%s\"\n",
-                      pkt_dev->ifname);
-               goto out_put;
-       }
-       if (!netif_running(odev)) {
-               printk("pktgen: device is down: \"%s\"\n", pkt_dev->ifname);
-               goto out_put;
+               printk("pktgen: not an ethernet device: \"%s\"\n", ifname);
+               err = -EINVAL;
+       } else if (!netif_running(odev)) {
+               printk("pktgen: device is down: \"%s\"\n", ifname);
+               err = -ENETDOWN;
+       } else {
+               pkt_dev->odev = odev;
+               return 0;
        }
-       pkt_dev->odev = odev;
-
-       return pkt_dev->odev;
 
-out_put:
        dev_put(odev);
-out:
-       return NULL;
-
+       return err;
 }
 
 /* Read pkt_dev from the interface and set up internal pktgen_dev
@@ -1955,10 +1950,6 @@ out:
  */
 static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
 {
-       /* Try once more, just in case it works now. */
-       if (!pkt_dev->odev)
-               pktgen_setup_dev(pkt_dev);
-
        if (!pkt_dev->odev) {
                printk("pktgen: ERROR: pkt_dev->odev == NULL in setup_inject.\n");
                sprintf(pkt_dev->result,
@@ -2095,7 +2086,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
        int flow = 0;
 
        if (pkt_dev->cflows) {
-               flow = pktgen_random() % pkt_dev->cflows;
+               flow = random32() % pkt_dev->cflows;
 
                if (pkt_dev->flows[flow].count > pkt_dev->lflow)
                        pkt_dev->flows[flow].count = 0;
@@ -2107,7 +2098,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
                __u32 tmp;
 
                if (pkt_dev->flags & F_MACSRC_RND)
-                       mc = pktgen_random() % (pkt_dev->src_mac_count);
+                       mc = random32() % pkt_dev->src_mac_count;
                else {
                        mc = pkt_dev->cur_src_mac_offset++;
                        if (pkt_dev->cur_src_mac_offset >
@@ -2133,7 +2124,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
                __u32 tmp;
 
                if (pkt_dev->flags & F_MACDST_RND)
-                       mc = pktgen_random() % (pkt_dev->dst_mac_count);
+                       mc = random32() % pkt_dev->dst_mac_count;
 
                else {
                        mc = pkt_dev->cur_dst_mac_offset++;
@@ -2160,24 +2151,23 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
                for(i = 0; i < pkt_dev->nr_labels; i++)
                        if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM)
                                pkt_dev->labels[i] = MPLS_STACK_BOTTOM |
-                                            ((__force __be32)pktgen_random() &
+                                            ((__force __be32)random32() &
                                                      htonl(0x000fffff));
        }
 
        if ((pkt_dev->flags & F_VID_RND) && (pkt_dev->vlan_id != 0xffff)) {
-               pkt_dev->vlan_id = pktgen_random() % 4096;
+               pkt_dev->vlan_id = random32() & (4096-1);
        }
 
        if ((pkt_dev->flags & F_SVID_RND) && (pkt_dev->svlan_id != 0xffff)) {
-               pkt_dev->svlan_id = pktgen_random() % 4096;
+               pkt_dev->svlan_id = random32() & (4096 - 1);
        }
 
        if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
                if (pkt_dev->flags & F_UDPSRC_RND)
-                       pkt_dev->cur_udp_src =
-                           ((pktgen_random() %
-                             (pkt_dev->udp_src_max - pkt_dev->udp_src_min)) +
-                            pkt_dev->udp_src_min);
+                       pkt_dev->cur_udp_src = random32() %
+                               (pkt_dev->udp_src_max - pkt_dev->udp_src_min)
+                               + pkt_dev->udp_src_min;
 
                else {
                        pkt_dev->cur_udp_src++;
@@ -2188,10 +2178,9 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 
        if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) {
                if (pkt_dev->flags & F_UDPDST_RND) {
-                       pkt_dev->cur_udp_dst =
-                           ((pktgen_random() %
-                             (pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)) +
-                            pkt_dev->udp_dst_min);
+                       pkt_dev->cur_udp_dst = random32() %
+                               (pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)
+                               + pkt_dev->udp_dst_min;
                } else {
                        pkt_dev->cur_udp_dst++;
                        if (pkt_dev->cur_udp_dst >= pkt_dev->udp_dst_max)
@@ -2206,7 +2195,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
                                                               saddr_max))) {
                        __u32 t;
                        if (pkt_dev->flags & F_IPSRC_RND)
-                               t = ((pktgen_random() % (imx - imn)) + imn);
+                               t = random32() % (imx - imn) + imn;
                        else {
                                t = ntohl(pkt_dev->cur_saddr);
                                t++;
@@ -2227,14 +2216,13 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
                                __be32 s;
                                if (pkt_dev->flags & F_IPDST_RND) {
 
-                                       t = pktgen_random() % (imx - imn) + imn;
+                                       t = random32() % (imx - imn) + imn;
                                        s = htonl(t);
 
                                        while (LOOPBACK(s) || MULTICAST(s)
                                               || BADCLASS(s) || ZERONET(s)
                                               || LOCAL_MCAST(s)) {
-                                               t = (pktgen_random() %
-                                                     (imx - imn)) + imn;
+                                               t = random32() % (imx - imn) + imn;
                                                s = htonl(t);
                                        }
                                        pkt_dev->cur_daddr = s;
@@ -2266,7 +2254,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 
                        for (i = 0; i < 4; i++) {
                                pkt_dev->cur_in6_daddr.s6_addr32[i] =
-                                   (((__force __be32)pktgen_random() |
+                                   (((__force __be32)random32() |
                                      pkt_dev->min_in6_daddr.s6_addr32[i]) &
                                     pkt_dev->max_in6_daddr.s6_addr32[i]);
                        }
@@ -2276,9 +2264,9 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
        if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) {
                __u32 t;
                if (pkt_dev->flags & F_TXSIZE_RND) {
-                       t = ((pktgen_random() %
-                             (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size))
-                            + pkt_dev->min_pkt_size);
+                       t = random32() %
+                               (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size)
+                               + pkt_dev->min_pkt_size;
                } else {
                        t = pkt_dev->cur_pkt_size + 1;
                        if (t > pkt_dev->max_pkt_size)
@@ -2315,7 +2303,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        int datalen, iplen;
        struct iphdr *iph;
        struct pktgen_hdr *pgh = NULL;
-       __be16 protocol = __constant_htons(ETH_P_IP);
+       __be16 protocol = htons(ETH_P_IP);
        __be32 *mpls;
        __be16 *vlan_tci = NULL;                 /* Encapsulates priority and VLAN ID */
        __be16 *vlan_encapsulated_proto = NULL;  /* packet type ID field (or len) for VLAN tag */
@@ -2324,10 +2312,10 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
 
 
        if (pkt_dev->nr_labels)
-               protocol = __constant_htons(ETH_P_MPLS_UC);
+               protocol = htons(ETH_P_MPLS_UC);
 
        if (pkt_dev->vlan_id != 0xffff)
-               protocol = __constant_htons(ETH_P_8021Q);
+               protocol = htons(ETH_P_8021Q);
 
        /* Update any of the values, used when we're incrementing various
         * fields.
@@ -2359,14 +2347,14 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
                                               pkt_dev->svlan_cfi,
                                               pkt_dev->svlan_p);
                        svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
-                       *svlan_encapsulated_proto = __constant_htons(ETH_P_8021Q);
+                       *svlan_encapsulated_proto = htons(ETH_P_8021Q);
                }
                vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
                *vlan_tci = build_tci(pkt_dev->vlan_id,
                                      pkt_dev->vlan_cfi,
                                      pkt_dev->vlan_p);
                vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
-               *vlan_encapsulated_proto = __constant_htons(ETH_P_IP);
+               *vlan_encapsulated_proto = htons(ETH_P_IP);
        }
 
        iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
@@ -2653,7 +2641,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        int datalen;
        struct ipv6hdr *iph;
        struct pktgen_hdr *pgh = NULL;
-       __be16 protocol = __constant_htons(ETH_P_IPV6);
+       __be16 protocol = htons(ETH_P_IPV6);
        __be32 *mpls;
        __be16 *vlan_tci = NULL;                 /* Encapsulates priority and VLAN ID */
        __be16 *vlan_encapsulated_proto = NULL;  /* packet type ID field (or len) for VLAN tag */
@@ -2661,10 +2649,10 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
 
        if (pkt_dev->nr_labels)
-               protocol = __constant_htons(ETH_P_MPLS_UC);
+               protocol = htons(ETH_P_MPLS_UC);
 
        if (pkt_dev->vlan_id != 0xffff)
-               protocol = __constant_htons(ETH_P_8021Q);
+               protocol = htons(ETH_P_8021Q);
 
        /* Update any of the values, used when we're incrementing various
         * fields.
@@ -2695,14 +2683,14 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
                                               pkt_dev->svlan_cfi,
                                               pkt_dev->svlan_p);
                        svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
-                       *svlan_encapsulated_proto = __constant_htons(ETH_P_8021Q);
+                       *svlan_encapsulated_proto = htons(ETH_P_8021Q);
                }
                vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
                *vlan_tci = build_tci(pkt_dev->vlan_id,
                                      pkt_dev->vlan_cfi,
                                      pkt_dev->vlan_p);
                vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
-               *vlan_encapsulated_proto = __constant_htons(ETH_P_IPV6);
+               *vlan_encapsulated_proto = htons(ETH_P_IPV6);
        }
 
        iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
@@ -2728,7 +2716,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        udph->len = htons(datalen + sizeof(struct udphdr));
        udph->check = 0;        /* No checksum */
 
-       *(__be32 *) iph = __constant_htonl(0x60000000); /* Version + flow */
+       *(__be32 *) iph = htonl(0x60000000);    /* Version + flow */
 
        if (pkt_dev->traffic_class) {
                /* Version + traffic class + flow (0) */
@@ -2847,7 +2835,7 @@ static void pktgen_run(struct pktgen_thread *t)
        struct pktgen_dev *pkt_dev;
        int started = 0;
 
-       PG_DEBUG(printk("pktgen: entering pktgen_run. %p\n", t));
+       pr_debug("pktgen: entering pktgen_run. %p\n", t);
 
        if_lock(t);
        list_for_each_entry(pkt_dev, &t->if_list, list) {
@@ -2879,7 +2867,7 @@ static void pktgen_stop_all_threads_ifs(void)
 {
        struct pktgen_thread *t;
 
-       PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads_ifs.\n"));
+       pr_debug("pktgen: entering pktgen_stop_all_threads_ifs.\n");
 
        mutex_lock(&pktgen_thread_lock);
 
@@ -2947,7 +2935,7 @@ static void pktgen_run_all_threads(void)
 {
        struct pktgen_thread *t;
 
-       PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n"));
+       pr_debug("pktgen: entering pktgen_run_all_threads.\n");
 
        mutex_lock(&pktgen_thread_lock);
 
@@ -3005,7 +2993,7 @@ static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
 
        if (!pkt_dev->running) {
                printk("pktgen: interface: %s is already stopped\n",
-                      pkt_dev->ifname);
+                      pkt_dev->odev->name);
                return -EINVAL;
        }
 
@@ -3039,7 +3027,7 @@ static void pktgen_stop(struct pktgen_thread *t)
 {
        struct pktgen_dev *pkt_dev;
 
-       PG_DEBUG(printk("pktgen: entering pktgen_stop\n"));
+       pr_debug("pktgen: entering pktgen_stop\n");
 
        if_lock(t);
 
@@ -3063,7 +3051,7 @@ static void pktgen_rem_one_if(struct pktgen_thread *t)
        struct list_head *q, *n;
        struct pktgen_dev *cur;
 
-       PG_DEBUG(printk("pktgen: entering pktgen_rem_one_if\n"));
+       pr_debug("pktgen: entering pktgen_rem_one_if\n");
 
        if_lock(t);
 
@@ -3092,7 +3080,7 @@ static void pktgen_rem_all_ifs(struct pktgen_thread *t)
 
        /* Remove all devices, free mem */
 
-       PG_DEBUG(printk("pktgen: entering pktgen_rem_all_ifs\n"));
+       pr_debug("pktgen: entering pktgen_rem_all_ifs\n");
        if_lock(t);
 
        list_for_each_safe(q, n, &t->if_list) {
@@ -3275,7 +3263,7 @@ static int pktgen_thread_worker(void *arg)
 
        t->pid = current->pid;
 
-       PG_DEBUG(printk("pktgen: starting pktgen/%d:  pid=%d\n", cpu, current->pid));
+       pr_debug("pktgen: starting pktgen/%d:  pid=%d\n", cpu, current->pid);
 
        max_before_softirq = t->max_before_softirq;
 
@@ -3333,16 +3321,18 @@ static int pktgen_thread_worker(void *arg)
                        t->control &= ~(T_REMDEV);
                }
 
+               try_to_freeze();
+
                set_current_state(TASK_INTERRUPTIBLE);
        }
 
-       PG_DEBUG(printk("pktgen: %s stopping all device\n", t->tsk->comm));
+       pr_debug("pktgen: %s stopping all device\n", t->tsk->comm);
        pktgen_stop(t);
 
-       PG_DEBUG(printk("pktgen: %s removing all device\n", t->tsk->comm));
+       pr_debug("pktgen: %s removing all device\n", t->tsk->comm);
        pktgen_rem_all_ifs(t);
 
-       PG_DEBUG(printk("pktgen: %s removing thread.\n", t->tsk->comm));
+       pr_debug("pktgen: %s removing thread.\n", t->tsk->comm);
        pktgen_rem_thread(t);
 
        return 0;
@@ -3355,13 +3345,13 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
        if_lock(t);
 
        list_for_each_entry(p, &t->if_list, list)
-               if (strncmp(p->ifname, ifname, IFNAMSIZ) == 0) {
+               if (strncmp(p->odev->name, ifname, IFNAMSIZ) == 0) {
                        pkt_dev = p;
                        break;
                }
 
        if_unlock(t);
-       PG_DEBUG(printk("pktgen: find_dev(%s) returning %p\n", ifname, pkt_dev));
+       pr_debug("pktgen: find_dev(%s) returning %p\n", ifname, pkt_dev);
        return pkt_dev;
 }
 
@@ -3396,7 +3386,7 @@ out:
 static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
 {
        struct pktgen_dev *pkt_dev;
-       struct proc_dir_entry *pe;
+       int err;
 
        /* We don't allow a device to be on several threads */
 
@@ -3438,29 +3428,28 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
        pkt_dev->svlan_cfi = 0;
        pkt_dev->svlan_id = 0xffff;
 
-       strncpy(pkt_dev->ifname, ifname, IFNAMSIZ);
+       err = pktgen_setup_dev(pkt_dev, ifname);
+       if (err)
+               goto out1;
 
-       if (!pktgen_setup_dev(pkt_dev)) {
-               printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
-               if (pkt_dev->flows)
-                       vfree(pkt_dev->flows);
-               kfree(pkt_dev);
-               return -ENODEV;
-       }
-
-       pe = create_proc_entry(ifname, 0600, pg_proc_dir);
-       if (!pe) {
+       pkt_dev->entry = create_proc_entry(ifname, 0600, pg_proc_dir);
+       if (!pkt_dev->entry) {
                printk("pktgen: cannot create %s/%s procfs entry.\n",
                       PG_PROC_DIR, ifname);
-               if (pkt_dev->flows)
-                       vfree(pkt_dev->flows);
-               kfree(pkt_dev);
-               return -EINVAL;
+               err = -EINVAL;
+               goto out2;
        }
-       pe->proc_fops = &pktgen_if_fops;
-       pe->data = pkt_dev;
+       pkt_dev->entry->proc_fops = &pktgen_if_fops;
+       pkt_dev->entry->data = pkt_dev;
 
        return add_dev_to_thread(t, pkt_dev);
+out2:
+       dev_put(pkt_dev->odev);
+out1:
+       if (pkt_dev->flows)
+               vfree(pkt_dev->flows);
+       kfree(pkt_dev);
+       return err;
 }
 
 static int __init pktgen_create_thread(int cpu)
@@ -3530,7 +3519,7 @@ static int pktgen_remove_device(struct pktgen_thread *t,
                                struct pktgen_dev *pkt_dev)
 {
 
-       PG_DEBUG(printk("pktgen: remove_device pkt_dev=%p\n", pkt_dev));
+       pr_debug("pktgen: remove_device pkt_dev=%p\n", pkt_dev);
 
        if (pkt_dev->running) {
                printk("pktgen:WARNING: trying to remove a running interface, stopping it now.\n");
@@ -3548,9 +3537,8 @@ static int pktgen_remove_device(struct pktgen_thread *t,
 
        _rem_dev_from_if_list(t, pkt_dev);
 
-       /* Clean up proc file system */
-
-       remove_proc_entry(pkt_dev->ifname, pg_proc_dir);
+       if (pkt_dev->entry)
+               remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);
 
        if (pkt_dev->flows)
                vfree(pkt_dev->flows);