patch-2.3.44 linux/drivers/net/hamradio/hdlcdrv.c

Next file: linux/drivers/net/hamradio/soundmodem/sm.c
Previous file: linux/drivers/net/hamradio/baycom_ser_hdx.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.43/linux/drivers/net/hamradio/hdlcdrv.c linux/drivers/net/hamradio/hdlcdrv.c
@@ -3,7 +3,7 @@
 /*
  *	hdlcdrv.c  -- HDLC packet radio network driver.
  *
- *	Copyright (C) 1996-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *	Copyright (C) 1996-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License as published by
@@ -27,16 +27,17 @@
  *	Written 1993-94 by Donald Becker.
  *
  *  History:
- *   0.1  21.09.96  Started
- *        18.10.96  Changed to new user space access routines 
- *                  (copy_{to,from}_user)
- *   0.2  21.11.96  various small changes
- *   0.3  03.03.97  fixed (hopefully) IP not working with ax.25 as a module
- *   0.4  16.04.97  init code/data tagged
- *   0.5  30.07.97  made HDLC buffers bigger (solves a problem with the
- *                  soundmodem driver)
- *   0.6  05.04.98  add spinlocks
- *   0.7  03.08.99  removed some old compatibility cruft
+ *   0.1  21.09.1996  Started
+ *        18.10.1996  Changed to new user space access routines 
+ *                    (copy_{to,from}_user)
+ *   0.2  21.11.1996  various small changes
+ *   0.3  03.03.1997  fixed (hopefully) IP not working with ax.25 as a module
+ *   0.4  16.04.1997  init code/data tagged
+ *   0.5  30.07.1997  made HDLC buffers bigger (solves a problem with the
+ *                    soundmodem driver)
+ *   0.6  05.04.1998  add spinlocks
+ *   0.7  03.08.1999  removed some old compatibility cruft
+ *   0.8  12.02.2000  adapted to softnet driver interface
  */
 
 /*****************************************************************************/
@@ -366,20 +367,16 @@
 				clear_bit(0, &s->hdlctx.in_hdlc_tx);
 				return;
 			}
-			if (!(skb = skb_dequeue(&s->send_queue))) {
-				int flgs = tenms_to_2flags
-					(s, s->ch_params.tx_tail);
+			if (!(skb = s->skb)) {
+				int flgs = tenms_to_2flags(s, s->ch_params.tx_tail);
 				if (flgs < 2)
 					flgs = 2;
 				s->hdlctx.tx_state = 1;
 				s->hdlctx.numflags = flgs;
 				break;
 			}
-			if (skb->data[0] != 0) {
-				do_kiss_params(s, skb->data, skb->len);
-				dev_kfree_skb(skb);
-				break;
-			}
+			s->skb = NULL;
+			netif_wake_queue(dev);
 			pkt_len = skb->len-1; /* strip KISS byte */
 			if (pkt_len >= HDLCDRV_MAXFLEN || pkt_len < 2) {
 				s->hdlctx.tx_state = 0;
@@ -454,8 +451,7 @@
 
 void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
 {
-	if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt || 
-	    skb_queue_empty(&s->send_queue)) 
+	if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt || !s->skb) 
 		return;
 	if (s->ch_params.fulldup) {
 		start_tx(dev, s);
@@ -499,8 +495,15 @@
 	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_send_packet"))
 		return 0;
 	sm = (struct hdlcdrv_state *)dev->priv;
-	skb_queue_tail(&sm->send_queue, skb);
-	dev->trans_start = jiffies;	
+	if (skb->data[0] != 0) {
+		do_kiss_params(sm, skb->data, skb->len);
+		dev_kfree_skb(skb);
+		return 0;
+	}
+	if (sm->skb)
+		return -1;
+	netif_stop_queue(dev);
+	sm->skb = skb;
 	return 0;
 }
 
@@ -550,12 +553,9 @@
 		return -EINVAL;
 	s = (struct hdlcdrv_state *)dev->priv;
 
-	if (dev->start)
-		return 0;
 	if (!s->ops || !s->ops->open)
 		return -ENODEV;
 
-	dev->start = 1;
 	/*
 	 * initialise some variables
 	 */
@@ -573,14 +573,9 @@
 	s->hdlctx.calibrate = 0;
 
 	i = s->ops->open(dev);
-	if (i) {
-		dev->start = 0;
+	if (i)
 		return i;
-	}
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-
+	netif_start_queue(dev);
 	return 0;
 }
 
@@ -592,23 +587,17 @@
 static int hdlcdrv_close(struct net_device *dev)
 {
 	struct hdlcdrv_state *s;
-	struct sk_buff *skb;
 	int i = 0;
 
 	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_close"))
 		return -EINVAL;
 	s = (struct hdlcdrv_state *)dev->priv;
 
-	if (!dev->start)
-		return 0;
-	dev->start = 0;
-	dev->tbusy = 1;
-
 	if (s->ops && s->ops->close)
 		i = s->ops->close(dev);
-        /* Free any buffers left in the hardware transmit queue */
-        while ((skb = skb_dequeue(&s->send_queue)))
-			dev_kfree_skb(skb);
+	if (s->skb)
+		dev_kfree_skb(s->skb);
+	s->skb = NULL;
 	return i;
 }
 
@@ -667,7 +656,7 @@
 		break;
 
 	case HDLCDRVCTL_SETMODEMPAR:
-		if ((!suser()) || dev->start)
+		if ((!suser()) || test_bit(LINK_STATE_START, &dev->state))
 			return -EACCES;
 		dev->base_addr = bi.data.mp.iobase;
 		dev->irq = bi.data.mp.irq;
@@ -801,10 +790,9 @@
 	dev->get_stats = hdlcdrv_get_stats;
 
 	/* Fill in the fields of the device structure */
-
 	dev_init_buffers(dev);
 
-	skb_queue_head_init(&s->send_queue);
+	s->skb = NULL;
 	
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 	dev->hard_header = ax25_encapsulate;
@@ -821,6 +809,7 @@
 	dev->addr_len = AX25_ADDR_LEN;     /* sizeof an ax.25 address */
 	memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
 	memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
+	dev->tx_queue_len = 16;
 
 	/* New style flags */
 	dev->flags = 0;
@@ -857,8 +846,6 @@
 	dev->name = s->ifname;
 	dev->if_port = 0;
 	dev->init = hdlcdrv_probe;
-	dev->start = 0;
-	dev->tbusy = 1;
 	dev->base_addr = baseaddr;
 	dev->irq = irq;
 	dev->dma = dma;
@@ -884,7 +871,7 @@
 		return -EINVAL;
 	if (s->magic != HDLCDRV_MAGIC)
 		return -EINVAL;
-	if (dev->start && s->ops->close)
+	if (s->ops->close)
 		s->ops->close(dev);
 	unregister_netdev(dev);
 	kfree(s);
@@ -911,8 +898,8 @@
 
 int __init init_module(void)
 {
-	printk(KERN_INFO "hdlcdrv: (C) 1996 Thomas Sailer HB9JNX/AE4WA\n");
-	printk(KERN_INFO "hdlcdrv: version 0.7 compiled " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA\n");
+	printk(KERN_INFO "hdlcdrv: version 0.8 compiled " __TIME__ " " __DATE__ "\n");
 	return 0;
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)