]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/net/hamradio/mkiss.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux-2.6.git] / drivers / net / hamradio / mkiss.c
index c6ca47599fd4581b1c6f24aaedb27ce0efb991a2..4c628393c8b157cbc09de52d902b5fa8c3d370a3 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/inet.h>
+#include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
@@ -36,6 +37,7 @@
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/jiffies.h>
+#include <linux/compat.h>
 
 #include <net/ax25.h>
 
@@ -59,8 +61,6 @@ struct mkiss {
        unsigned char           *xhead; /* pointer to next byte to XMIT */
        int                     xleft;  /* bytes left in XMIT queue     */
 
-       struct net_device_stats stats;
-
        /* Detailed SLIP statistics. */
        int             mtu;            /* Our mtu (to spot changes!)   */
        int             buffsize;       /* Max buffers sizes            */
@@ -253,14 +253,14 @@ static void ax_bump(struct mkiss *ax)
        if (ax->rbuff[0] > 0x0f) {
                if (ax->rbuff[0] & 0x80) {
                        if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
-                               ax->stats.rx_errors++;
+                               ax->dev->stats.rx_errors++;
                                spin_unlock_bh(&ax->buflock);
 
                                return;
                        }
                        if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
                                printk(KERN_INFO
-                                      "mkiss: %s: Switchting to crc-smack\n",
+                                      "mkiss: %s: Switching to crc-smack\n",
                                       ax->dev->name);
                                ax->crcmode = CRC_MODE_SMACK;
                        }
@@ -268,13 +268,13 @@ static void ax_bump(struct mkiss *ax)
                        *ax->rbuff &= ~0x80;
                } else if (ax->rbuff[0] & 0x20)  {
                        if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
-                               ax->stats.rx_errors++;
+                               ax->dev->stats.rx_errors++;
                                spin_unlock_bh(&ax->buflock);
                                return;
                        }
                        if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
                                printk(KERN_INFO
-                                      "mkiss: %s: Switchting to crc-flexnet\n",
+                                      "mkiss: %s: Switching to crc-flexnet\n",
                                       ax->dev->name);
                                ax->crcmode = CRC_MODE_FLEX;
                        }
@@ -295,7 +295,7 @@ static void ax_bump(struct mkiss *ax)
        if ((skb = dev_alloc_skb(count)) == NULL) {
                printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n",
                       ax->dev->name);
-               ax->stats.rx_dropped++;
+               ax->dev->stats.rx_dropped++;
                spin_unlock_bh(&ax->buflock);
                return;
        }
@@ -303,9 +303,8 @@ static void ax_bump(struct mkiss *ax)
        memcpy(skb_put(skb,count), ax->rbuff, count);
        skb->protocol = ax25_type_trans(skb, ax->dev);
        netif_rx(skb);
-       ax->dev->last_rx = jiffies;
-       ax->stats.rx_packets++;
-       ax->stats.rx_bytes += count;
+       ax->dev->stats.rx_packets++;
+       ax->dev->stats.rx_bytes += count;
        spin_unlock_bh(&ax->buflock);
 }
 
@@ -345,7 +344,7 @@ static void kiss_unesc(struct mkiss *ax, unsigned char s)
                        return;
                }
 
-               ax->stats.rx_over_errors++;
+               ax->dev->stats.rx_over_errors++;
                set_bit(AXF_ERROR, &ax->flags);
        }
        spin_unlock_bh(&ax->buflock);
@@ -356,7 +355,9 @@ static int ax_set_mac_address(struct net_device *dev, void *addr)
        struct sockaddr_ax25 *sa = addr;
 
        netif_tx_lock_bh(dev);
+       netif_addr_lock(dev);
        memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
+       netif_addr_unlock(dev);
        netif_tx_unlock_bh(dev);
 
        return 0;
@@ -405,7 +406,7 @@ static void ax_changedmtu(struct mkiss *ax)
                        memcpy(ax->xbuff, ax->xhead, ax->xleft);
                } else  {
                        ax->xleft = 0;
-                       ax->stats.tx_dropped++;
+                       dev->stats.tx_dropped++;
                }
        }
 
@@ -416,7 +417,7 @@ static void ax_changedmtu(struct mkiss *ax)
                        memcpy(ax->rbuff, orbuff, ax->rcount);
                } else  {
                        ax->rcount = 0;
-                       ax->stats.rx_over_errors++;
+                       dev->stats.rx_over_errors++;
                        set_bit(AXF_ERROR, &ax->flags);
                }
        }
@@ -443,7 +444,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
        if (len > ax->mtu) {            /* Sigh, shouldn't occur BUT ... */
                len = ax->mtu;
                printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);
-               ax->stats.tx_dropped++;
+               dev->stats.tx_dropped++;
                netif_start_queue(dev);
                return;
        }
@@ -517,8 +518,8 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
 
        set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
        actual = ax->tty->ops->write(ax->tty, ax->xbuff, count);
-       ax->stats.tx_packets++;
-       ax->stats.tx_bytes += actual;
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes += actual;
 
        ax->dev->trans_start = jiffies;
        ax->xleft = count - actual;
@@ -526,13 +527,13 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
 }
 
 /* Encapsulate an AX.25 packet and kick it into a TTY queue. */
-static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t ax_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct mkiss *ax = netdev_priv(dev);
 
        if (!netif_running(dev))  {
                printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
-               return 1;
+               return NETDEV_TX_BUSY;
        }
 
        if (netif_queue_stopped(dev)) {
@@ -542,11 +543,11 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
                 */
                if (time_before(jiffies, dev->trans_start + 20 * HZ)) {
                        /* 20 sec timeout not reached */
-                       return 1;
+                       return NETDEV_TX_BUSY;
                }
 
                printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
-                      (ax->tty->ops->chars_in_buffer(ax->tty) || ax->xleft) ?
+                      (tty_chars_in_buffer(ax->tty) || ax->xleft) ?
                       "bad line quality" : "driver error");
 
                ax->xleft = 0;
@@ -561,7 +562,7 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
                kfree_skb(skb);
        }
 
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static int ax_open_dev(struct net_device *dev)
@@ -663,32 +664,28 @@ static int ax_close(struct net_device *dev)
        return 0;
 }
 
-static struct net_device_stats *ax_get_stats(struct net_device *dev)
-{
-       struct mkiss *ax = netdev_priv(dev);
-
-       return &ax->stats;
-}
-
 static const struct header_ops ax_header_ops = {
        .create    = ax_header,
        .rebuild   = ax_rebuild_header,
 };
 
+static const struct net_device_ops ax_netdev_ops = {
+       .ndo_open            = ax_open_dev,
+       .ndo_stop            = ax_close,
+       .ndo_start_xmit      = ax_xmit,
+       .ndo_set_mac_address = ax_set_mac_address,
+};
+
 static void ax_setup(struct net_device *dev)
 {
        /* Finish setting up the DEVICE info. */
        dev->mtu             = AX_MTU;
-       dev->hard_start_xmit = ax_xmit;
-       dev->open            = ax_open_dev;
-       dev->stop            = ax_close;
-       dev->get_stats       = ax_get_stats;
-       dev->set_mac_address = ax_set_mac_address;
        dev->hard_header_len = 0;
        dev->addr_len        = 0;
        dev->type            = ARPHRD_AX25;
        dev->tx_queue_len    = 10;
        dev->header_ops      = &ax_header_ops;
+       dev->netdev_ops      = &ax_netdev_ops;
 
 
        memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
@@ -750,7 +747,7 @@ static int mkiss_open(struct tty_struct *tty)
 
        spin_lock_init(&ax->buflock);
        atomic_set(&ax->refcnt, 1);
-       init_MUTEX_LOCKED(&ax->dead_sem);
+       sema_init(&ax->dead_sem, 0);
 
        ax->tty = tty;
        tty->disc_data = ax;
@@ -845,12 +842,13 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
        unsigned int cmd, unsigned long arg)
 {
        struct mkiss *ax = mkiss_get(tty);
-       struct net_device *dev = ax->dev;
+       struct net_device *dev;
        unsigned int tmp, err;
 
        /* First make sure we're connected. */
        if (ax == NULL)
                return -ENXIO;
+       dev = ax->dev;
 
        switch (cmd) {
        case SIOCGIFNAME:
@@ -902,6 +900,23 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
        return err;
 }
 
+#ifdef CONFIG_COMPAT
+static long mkiss_compat_ioctl(struct tty_struct *tty, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       case SIOCGIFNAME:
+       case SIOCGIFENCAP:
+       case SIOCSIFENCAP:
+       case SIOCSIFHWADDR:
+               return mkiss_ioctl(tty, file, cmd,
+                                  (unsigned long)compat_ptr(arg));
+       }
+
+       return -ENOIOCTLCMD;
+}
+#endif
+
 /*
  * Handle the 'receiver data ready' interrupt.
  * This function is called by the 'tty_io' module in the kernel when
@@ -927,7 +942,7 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
        while (count--) {
                if (fp != NULL && *fp++) {
                        if (!test_and_set_bit(AXF_ERROR, &ax->flags))
-                               ax->stats.rx_errors++;
+                               ax->dev->stats.rx_errors++;
                        cp++;
                        continue;
                }
@@ -976,13 +991,16 @@ static struct tty_ldisc_ops ax_ldisc = {
        .open           = mkiss_open,
        .close          = mkiss_close,
        .ioctl          = mkiss_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = mkiss_compat_ioctl,
+#endif
        .receive_buf    = mkiss_receive_buf,
        .write_wakeup   = mkiss_write_wakeup
 };
 
-static char banner[] __initdata = KERN_INFO \
+static const char banner[] __initdata = KERN_INFO \
        "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
-static char msg_regfail[] __initdata = KERN_ERR \
+static const char msg_regfail[] __initdata = KERN_ERR \
        "mkiss: can't register line discipline (err = %d)\n";
 
 static int __init mkiss_init_driver(void)
@@ -991,8 +1009,9 @@ static int __init mkiss_init_driver(void)
 
        printk(banner);
 
-       if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0)
-               printk(msg_regfail);
+       status = tty_register_ldisc(N_AX25, &ax_ldisc);
+       if (status != 0)
+               printk(msg_regfail, status);
 
        return status;
 }