diff options
Diffstat (limited to 'drivers/net/hamradio/mkiss.c')
| -rw-r--r-- | drivers/net/hamradio/mkiss.c | 179 |
1 files changed, 95 insertions, 84 deletions
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 3e9accf137e..8a6c720a4cc 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -9,16 +9,13 @@ * for more details. * * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * with this program; if not, see <http://www.gnu.org/licenses/>. * * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl> * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org> * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de> */ -#include <linux/config.h> #include <linux/module.h> -#include <asm/system.h> #include <linux/bitops.h> #include <asm/uaccess.h> #include <linux/crc16.h> @@ -27,6 +24,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> @@ -37,6 +35,7 @@ #include <linux/skbuff.h> #include <linux/if_arp.h> #include <linux/jiffies.h> +#include <linux/compat.h> #include <net/ax25.h> @@ -60,8 +59,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 */ @@ -254,14 +251,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; } @@ -269,13 +266,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; } @@ -290,25 +287,23 @@ static void ax_bump(struct mkiss *ax) *ax->rbuff &= ~0x20; } } - spin_unlock_bh(&ax->buflock); count = ax->rcount; 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; } - spin_lock_bh(&ax->buflock); memcpy(skb_put(skb,count), ax->rbuff, count); - spin_unlock_bh(&ax->buflock); 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); } static void kiss_unesc(struct mkiss *ax, unsigned char s) @@ -347,7 +342,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); @@ -357,9 +352,11 @@ static int ax_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr_ax25 *sa = addr; - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); + netif_addr_lock(dev); memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_addr_unlock(dev); + netif_tx_unlock_bh(dev); return 0; } @@ -407,7 +404,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++; } } @@ -418,7 +415,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); } } @@ -445,7 +442,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; } @@ -487,7 +484,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) return; default: - count = kiss_esc(p, (unsigned char *)ax->xbuff, len); + count = kiss_esc(p, ax->xbuff, len); } } else { unsigned short crc; @@ -499,7 +496,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) case CRC_MODE_SMACK: *p |= 0x80; crc = swab16(crc16(0, p, len)); - count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2); + count = kiss_esc_crc(p, ax->xbuff, crc, len+2); break; case CRC_MODE_FLEX_TEST: ax->crcmode = CRC_MODE_NONE; @@ -508,18 +505,19 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) case CRC_MODE_FLEX: *p |= 0x20; crc = calc_crc_flex(p, len); - count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2); + count = kiss_esc_crc(p, ax->xbuff, crc, len+2); break; default: - count = kiss_esc(p, (unsigned char *)ax->xbuff, len); + count = kiss_esc(p, ax->xbuff, len); } } + spin_unlock_bh(&ax->buflock); set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags); - actual = ax->tty->driver->write(ax->tty, ax->xbuff, count); - ax->stats.tx_packets++; - ax->stats.tx_bytes += actual; + actual = ax->tty->ops->write(ax->tty, ax->xbuff, count); + dev->stats.tx_packets++; + dev->stats.tx_bytes += actual; ax->dev->trans_start = jiffies; ax->xleft = count - actual; @@ -527,13 +525,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)) { @@ -543,11 +541,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->driver->chars_in_buffer(ax->tty) || ax->xleft) ? + (tty_chars_in_buffer(ax->tty) || ax->xleft) ? "bad line quality" : "driver error"); ax->xleft = 0; @@ -562,7 +560,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) @@ -578,11 +576,12 @@ static int ax_open_dev(struct net_device *dev) #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) /* Return the frame type ID */ -static int ax_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - void *daddr, void *saddr, unsigned len) +static int ax_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, + const void *saddr, unsigned len) { #ifdef CONFIG_INET - if (type != htons(ETH_P_AX25)) + if (type != ETH_P_AX25) return ax25_hard_header(skb, dev, type, daddr, saddr, len); #endif return 0; @@ -663,36 +662,32 @@ 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); +static const struct header_ops ax_header_ops = { + .create = ax_header, + .rebuild = ax_rebuild_header, +}; - return &ax->stats; -} +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) { - static char ax25_bcast[AX25_ADDR_LEN] = - {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1}; - static char ax25_test[AX25_ADDR_LEN] = - {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1}; - /* 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->hard_header = ax_header; - dev->rebuild_header = ax_rebuild_header; + dev->header_ops = &ax_header_ops; + dev->netdev_ops = &ax_netdev_ops; + - memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); - memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); + memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); + memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); dev->flags = IFF_BROADCAST | IFF_MULTICAST; } @@ -736,6 +731,8 @@ static int mkiss_open(struct tty_struct *tty) if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (tty->ops->write == NULL) + return -EOPNOTSUPP; dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup); if (!dev) { @@ -748,13 +745,13 @@ 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; + tty->receive_room = 65535; - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); + tty_driver_flush_buffer(tty); /* Restore default settings */ dev->type = ARPHRD_AX25; @@ -814,12 +811,12 @@ static void mkiss_close(struct tty_struct *tty) { struct mkiss *ax; - write_lock(&disc_data_lock); + write_lock_bh(&disc_data_lock); ax = tty->disc_data; tty->disc_data = NULL; - write_unlock(&disc_data_lock); + write_unlock_bh(&disc_data_lock); - if (ax == 0) + if (!ax) return; /* @@ -843,12 +840,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: @@ -884,9 +882,9 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file, break; } - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); memcpy(dev->dev_addr, addr, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_tx_unlock_bh(dev); err = 0; break; @@ -900,6 +898,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 @@ -925,7 +940,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; } @@ -934,14 +949,7 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp, } mkiss_put(ax); - if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) - && tty->driver->unthrottle) - tty->driver->unthrottle(tty); -} - -static int mkiss_receive_room(struct tty_struct *tty) -{ - return 65536; /* We can handle an infinite amount of data. :-) */ + tty_unthrottle(tty); } /* @@ -966,7 +974,7 @@ static void mkiss_write_wakeup(struct tty_struct *tty) goto out; } - actual = tty->driver->write(tty, ax->xhead, ax->xleft); + actual = tty->ops->write(tty, ax->xhead, ax->xleft); ax->xleft -= actual; ax->xhead += actual; @@ -974,21 +982,23 @@ out: mkiss_put(ax); } -static struct tty_ldisc ax_ldisc = { +static struct tty_ldisc_ops ax_ldisc = { .owner = THIS_MODULE, .magic = TTY_LDISC_MAGIC, .name = "mkiss", .open = mkiss_open, .close = mkiss_close, .ioctl = mkiss_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = mkiss_compat_ioctl, +#endif .receive_buf = mkiss_receive_buf, - .receive_room = mkiss_receive_room, .write_wakeup = mkiss_write_wakeup }; -static char banner[] __initdata = KERN_INFO \ +static const char banner[] __initconst = KERN_INFO \ "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n"; -static char msg_regfail[] __initdata = KERN_ERR \ +static const char msg_regfail[] __initconst = KERN_ERR \ "mkiss: can't register line discipline (err = %d)\n"; static int __init mkiss_init_driver(void) @@ -997,13 +1007,14 @@ 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; } -static const char msg_unregfail[] __exitdata = KERN_ERR \ +static const char msg_unregfail[] = KERN_ERR \ "mkiss: can't unregister line discipline (err = %d)\n"; static void __exit mkiss_exit_driver(void) @@ -1016,7 +1027,7 @@ static void __exit mkiss_exit_driver(void) MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>"); MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs"); -MODULE_PARM(crc_force, "i"); +module_param(crc_force, int, 0); MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]"); MODULE_LICENSE("GPL"); MODULE_ALIAS_LDISC(N_AX25); |
