aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/hamradio/mkiss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/hamradio/mkiss.c')
-rw-r--r--drivers/net/hamradio/mkiss.c132
1 files changed, 74 insertions, 58 deletions
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 30c9b3b0d13..8a6c720a4cc 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -9,15 +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/module.h>
-#include <asm/system.h>
#include <linux/bitops.h>
#include <asm/uaccess.h>
#include <linux/crc16.h>
@@ -26,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>
@@ -36,6 +35,7 @@
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/jiffies.h>
+#include <linux/compat.h>
#include <net/ax25.h>
@@ -59,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 */
@@ -253,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;
}
@@ -268,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;
}
@@ -295,7 +293,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 +301,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 +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);
@@ -356,7 +353,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 +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++;
}
}
@@ -416,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);
}
}
@@ -443,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;
}
@@ -485,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;
@@ -497,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;
@@ -506,19 +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;
@@ -526,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)) {
@@ -542,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;
@@ -561,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)
@@ -663,32 +662,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);
@@ -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,14 +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;
@@ -815,10 +811,10 @@ 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)
return;
@@ -844,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:
@@ -901,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
@@ -926,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;
}
@@ -935,9 +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);
+ tty_unthrottle(tty);
}
/*
@@ -962,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;
@@ -970,20 +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,
.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)
@@ -992,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)