patch-2.2.19 linux/drivers/s390/net/ctc.c

Next file: linux/drivers/s390/net/iucv.c
Previous file: linux/drivers/s390/net/Makefile
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.18/drivers/s390/net/ctc.c linux/drivers/s390/net/ctc.c
@@ -1,5 +1,5 @@
 /*
- * $Id: ctc.c,v 1.25.2.5 2000/10/11 15:08:59 bird Exp $
+ * $Id: ctc.c,v 1.29 2001/01/25 22:28:21 uweigand Exp $
  *
  *  drivers/s390/net/ctc.c 
  *    CTC / ESCON network driver
@@ -22,12 +22,13 @@
  *    order or doesn't want to have automatic channel selection on, you can do 
  *    this with the "ctc= kernel keyword". 
  *
- *	 ctc=0,0xrrrr,0xwwww,ddddd
+ *	 ctc=prid,0xrrrr,0xwwww,ddddd
  *
  *     Where:
  *
- *	 "rrrr" is the read channel address
- *	 "wwww" is the write channel address
+ *       "prid" is the protocol id (must always be 0)
+ *	 "rrrr" is the read channel address (hexadecimal)
+ *	 "wwww" is the write channel address (hexadecimal)
  *	 "dddd" is the network device (ctc0 to ctc7 for a parallel channel, escon0
  *		to escon7 for ESCON channels).
  *
@@ -38,24 +39,39 @@
  *	 ctc=noauto
  * 
  * $Log: ctc.c,v $
- * Revision 1.25.2.5  2000/10/11 15:08:59  bird
- * ctc_tx(): Quick fix of possible underflow when calculating free block space
+ * Revision 1.29  2001/01/25 22:28:21  uweigand
+ * Minor 2.2.18 fix.
  *
- * Revision 1.25.2.4  2000/09/25 16:40:56  bird
- * Some more debug information
+ * Revision 1.28  2001/01/18 13:04:47  tonn
+ * upgrade to 2.2.18
  *
- * Revision 1.25.2.3  2000/09/20 13:28:19  bird
- * - ctc_open(): fixed bug
- * - ctc_release(): added timer for terminating in case of halt_io()-hang
- *
- * Revision 1.25.2.2  2000/09/20 09:48:27  bird
- * - ctc_open()/ctc_release(): use wait_event_interruptible()/wait_event() in
- *   instead of direct waiting on a wait queue
- * - ctc_buffer_swap(), ccw_check_return_code() and ccw_check_unit_check():
- *   print more debug information
+ * Revision 1.27  2000/10/26 16:16:07  bird
+ * Merged in changes from Revision 1.25.2.1 to Revision 1.25.2.6:
  *
- * Revision 1.25.2.1  2000/09/19 09:09:56  bird
- * Merged in changes from 1.25 to 1.26
+ *   Revision 1.25.2.6  2000/10/25 16:11:55  bird
+ *   Set size of empty block to BLOCK_HEADER_LENGTH (used to be 0)
+ *
+ *   Revision 1.25.2.5  2000/10/11 15:08:59  bird
+ *   ctc_tx(): Quick fix of possible underflow when calculating free block space
+ *
+ *   Revision 1.25.2.4  2000/09/25 16:40:56  bird
+ *   Some more debug information
+ *
+ *   Revision 1.25.2.3  2000/09/20 13:28:19  bird
+ *   - ctc_open(): fixed bug
+ *   - ctc_release(): added timer for terminating in case of halt_io()-hang
+ *
+ *   Revision 1.25.2.2  2000/09/20 09:48:27  bird
+ *   - ctc_open()/ctc_release(): use wait_event_interruptible()/wait_event() in
+ *     instead of direct waiting on a wait queue
+ *   - ctc_buffer_swap(), ccw_check_return_code() and ccw_check_unit_check():
+ *     print more debug information
+ *
+ *   Revision 1.25.2.1  2000/09/19 09:09:56  bird
+ *   Merged in changes from 1.25 to 1.26
+ *
+ * Revision 1.26  2000/09/15 12:29:32  weigand
+ * Some 2.3 diffs merged and other fixes.
  *
  * Revision 1.25  2000/09/08 09:22:11  bird
  * Proper cleanup and bugfixes in ctc_probe()
@@ -276,8 +292,6 @@
 typedef struct net_device  net_device;
 #else
 typedef struct device  net_device;
-typedef struct wait_queue* wait_queue_head_t;
-#define init_waitqueue_head(nothing)
 #endif
 
 struct adapterlist{ 
@@ -319,9 +333,9 @@
 #define CTC_BH_ACTIVE	    0	
 	__u8		    last_dstat;
 	__u8		    flag;
-#define CTC_WRITE      0x01      /* - Set if this is a write channel */
+#define CTC_WRITE	     0x01      /* - Set if this is a write channel */
 #define CTC_WAKEUP     0x02      /* - Set if this channel should wake up from waiting for an event */
-#define CTC_TIMER      0x80      /* - Set if timer made the wake_up  */ 
+#define CTC_TIMER	     0x80      /* - Set if timer made the wake_up  */ 
 };
 
 
@@ -352,6 +366,8 @@
 	__u16	      length;
 	struct packet data;
 };
+#define BLOCK_PAGES_POW 4    /* 2^4 = 16 pages per block (64k) */
+#define BLOCK_MAX_DATA 65535 /* maximal amount of data a block can hold */
 
 #if LINUX_VERSION_CODE>=0x02032D
 #define ctc_protect_busy(dev) \
@@ -485,7 +501,7 @@
  */
 static void print_banner(void) {
 	static int printed = 0;
-	char vbuf[] = "$Revision: 1.25.2.5 $";
+	char vbuf[] = "$Revision: 1.29 $";
 	char *version = vbuf;
 
 	if (printed)
@@ -763,12 +779,12 @@
 	else {	
 		p->next = NULL;	 
 		p->packets = 0;
-		p->block = (struct block *) __get_free_pages(GFP_KERNEL+GFP_DMA, 4);
+		p->block = (struct block *) __get_free_pages(GFP_KERNEL+GFP_DMA, BLOCK_PAGES_POW);
 		if (p->block == NULL) {
 			kfree(p);
 			return -ENOMEM;
 		}
-		p->block->length = 0; 
+		p->block->length = BLOCK_HEADER_LENGTH; /* empty block */
 	}
    
 	if (ctc->free_anchor == NULL) 
@@ -1109,7 +1125,7 @@
 
 } 
 
- 
+
 static void ctc_irq_handler (int irq, void *initparm, struct pt_regs *regs)
 {
 	int		  rc = 0;
@@ -1196,7 +1212,6 @@
 			wake_up(&ctc->wait);   /* wake up ctc_release */
 			return;
  
-
 		case CTC_START_HALT_IO:	 /* HALT_IO issued by ctc_open (start sequence) */
 #ifdef DEBUG
 		  printk(KERN_DEBUG "%s: %s(): entering state %s\n", dev->name, __FUNCTION__,  "CTC_START_HALT_IO");
@@ -1228,7 +1243,6 @@
 				return;
 			ctc->state =  CTC_START_SELECT;
  
-
 		case CTC_START_SELECT:
 #ifdef DEBUG
 		  printk(KERN_DEBUG "%s: %s(): entering state %s\n", dev->name, __FUNCTION__,  "CTC_START_SELECT");
@@ -1241,7 +1255,7 @@
 			}
 			if (!(ctc->flag & CTC_WRITE)) {
 				ctc->state = CTC_START_READ_TEST;
-				ctc->free_anchor->block->length = 0;	
+				ctc->free_anchor->block->length = BLOCK_HEADER_LENGTH; /* empty block */
 				ctc->ccw[1].cda	 = __pa(ctc->free_anchor->block);
 				parm = (__u32)(long) ctc;
 				rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags );
@@ -1253,7 +1267,7 @@
 			} else {
 				ctc->state = CTC_START_WRITE_TEST;
 				/* ADD HERE THE RIGHT PACKET TO ISSUE A ROUND TRIP - PART 1 */
-				ctc->free_anchor->block->length = 0;	
+				ctc->free_anchor->block->length = BLOCK_HEADER_LENGTH; /* empty block */
 				ctc->ccw[1].count = BLOCK_HEADER_LENGTH; /* Transfer only length */
 				ctc->ccw[1].cda	 = __pa(ctc->free_anchor->block);
 				parm = (__u32)(long) ctc; 
@@ -1263,7 +1277,6 @@
 			}
 			return;
 
-
 		case CTC_START_READ_TEST:
 #ifdef DEBUG
 		  printk(KERN_DEBUG "%s: %s(): entering state %s\n", dev->name, __FUNCTION__,  "CTC_START_READ_TEST");
@@ -1300,8 +1313,7 @@
 			/* ADD HERE THE RIGHT PACKET TO ISSUE A ROUND TRIP - PART 2 */
 			/* wake_up(&privptr->channel[WRITE].wait);*/  /* wake up ctc_open (WRITE) */
 
-
-		case CTC_START_READ:
+		case CTC_START_READ: 
 #ifdef DEBUG
 		  printk(KERN_DEBUG "%s: %s(): entering state %s\n", dev->name, __FUNCTION__,  "CTC_START_READ");
 #endif 
@@ -1333,7 +1345,7 @@
 			ctc_buffer_swap(&ctc->free_anchor, &ctc->proc_anchor, dev);
 
 			if (ctc->free_anchor != NULL) {
-				ctc->free_anchor->block->length = 0;
+				ctc->free_anchor->block->length = BLOCK_HEADER_LENGTH; /* empty block */
 				ctc->ccw[1].cda	 = __pa(ctc->free_anchor->block);
 				parm = (__u32)(long) ctc;
 				rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags );
@@ -1352,7 +1364,6 @@
 			}
 			return;
 
-
 		case CTC_START_WRITE_TEST:
 #ifdef DEBUG
 		  printk(KERN_DEBUG "%s: %s(): entering state %s\n", dev->name, __FUNCTION__,  "CTC_START_WRITE_TEST");
@@ -1378,7 +1389,6 @@
 			wake_up(&ctc->wait);  /* wake up ctc_open (WRITE) */
 			return;
  
-
 		case CTC_START_WRITE:
 #ifdef DEBUG
 		  printk(KERN_DEBUG "%s: %s(): entering state %s\n", dev->name, __FUNCTION__,  "CTC_START_WRITE");
@@ -1394,7 +1404,7 @@
 				privptr->stats.tx_packets += ctc->proc_anchor->packets;
 			} 
 
-			ctc->proc_anchor->block->length = 0;
+			ctc->proc_anchor->block->length = BLOCK_HEADER_LENGTH; /* empty block */
 			ctc_buffer_swap(&ctc->proc_anchor, &ctc->free_anchor, dev);
 			ctc_clearbit_busy(TB_NOBUFFER, dev);	 
 			if (ctc->proc_anchor != NULL) {	 
@@ -1416,7 +1426,7 @@
 							 "irq=%d, ctc=0x%p, dev=0x%p \n", irq, ctc, privptr);
 				return;
 			}
-			if (ctc->free_anchor->block->length != 0) {
+			if (ctc->free_anchor->block->length != BLOCK_HEADER_LENGTH) { /* non-empty block */
 				if (ctc_test_and_setbit_busy(TB_TX,dev) == 0) {	    
 				       /* set transmission to busy */
 					ctc_buffer_swap(&ctc->free_anchor, &ctc->proc_anchor, dev);
@@ -1470,15 +1480,17 @@
 
 	while (ctc->proc_anchor != NULL) {
 		block = ctc->proc_anchor->block;
-		if (block->length < BLOCK_HEADER_LENGTH) {
-			if(block->length == 0 && !ctc->initial_block_received)
-				ctc->initial_block_received = 1;
-			else
+
+		if ((block->length < BLOCK_HEADER_LENGTH)
+		    || (block->length == BLOCK_HEADER_LENGTH && ctc->initial_block_received)) {
 				printk(KERN_INFO "%s: %s(): discarding block at 0x%p: "
-				       "block length=%d<%d=block header length\n",
+					 "block length=%d<=%d=block header length\n",
 				       dev->name, __FUNCTION__, block, block->length, BLOCK_HEADER_LENGTH);
 		}
-		else {
+		else if(block->length == BLOCK_HEADER_LENGTH && !ctc->initial_block_received) {
+			ctc->initial_block_received = 1;
+		}
+		else { /* there is valid data in the buffer */
 			lp = &block->data;
 			while ((__u8 *) lp < (__u8 *) block + block->length) {
 				if(lp->length < PACKET_HEADER_LENGTH) {
@@ -1559,6 +1571,7 @@
 	       dev->name, ctc->state);
 #endif	
 	s390irq_spin_lock_irqsave(ctc->irq, saveflags);
+
 	if (ctc->state != CTC_STOP) {
 		if (!ctc->free_anchor) {
 			s390irq_spin_unlock_irqrestore(ctc->irq, saveflags);
@@ -1568,7 +1581,7 @@
 			return;
 		}
 
-		ctc->free_anchor->block->length = 0;
+		ctc->free_anchor->block->length = BLOCK_HEADER_LENGTH; /* empty block */
 		ctc->ccw[1].cda	 = __pa(ctc->free_anchor->block);
 		parm = (__u32)(long) ctc; 
 		rc = do_IO(ctc->irq, &ctc->ccw[0], parm, 0xff, flags);
@@ -1636,7 +1649,6 @@
 	struct ctc_priv	   *privptr;
 	struct timer_list  timer;
 
-
 	ctc_set_busy(dev);
 
 	privptr = (struct ctc_priv *) (dev->priv);
@@ -1698,13 +1710,13 @@
 		rc = halt_IO(privptr->channel[i].irq, parm, flags);
 		s390irq_spin_unlock_irqrestore(privptr->channel[i].irq, saveflags);
 
-		wait_rc = wait_event_interruptible(privptr->channel[i].wait, privptr->channel[i].flag & CTC_WAKEUP);
-
-		del_timer(&timer);
-
 		if(rc != 0)
 			ccw_check_return_code(dev, rc, __FUNCTION__ "()[1]");
 
+		wait_rc = wait_event_interruptible(privptr->channel[i].wait, privptr->channel[i].flag & CTC_WAKEUP);
+
+			del_timer(&timer);
+	
 		if (wait_rc == -ERESTARTSYS) { /* wait_event_interruptible() was terminated by a signal */
 			for (ii=0; ii<=i; ii++) {
 
@@ -1720,7 +1732,7 @@
 			return -ERESTARTSYS;
 		}
 	}
-	
+
 	if ((((privptr->channel[READ].last_dstat | privptr->channel[WRITE].last_dstat) & 
 	       ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) ||
 	    (((privptr->channel[READ].flag | privptr->channel[WRITE].flag) & CTC_TIMER) != 0x00)) {
@@ -1783,7 +1795,7 @@
 	ctc_setbit_busy(TB_STOP,dev);	 
 	ctc_unprotect_busy_irqrestore(dev, saveflags);
 
-	for (i = 0; i < 2;  i++) {
+	for (i = 0; i < 2;  i++) {		  
 		privptr->channel[i].flag &= ~(CTC_WAKEUP | CTC_TIMER);
 		init_timer(&timer);
 		timer.function = ctc_timer; 
@@ -1805,7 +1817,7 @@
 		if (rc != 0) {
 			ccw_check_return_code(dev, rc, __FUNCTION__ "()[1]");
 		}
-
+		 
 		if(privptr->channel[i].flag & CTC_TIMER)
 		{
 			printk(KERN_WARNING "%s: %s(): timeout during halt_io()\n",
@@ -1874,7 +1886,7 @@
 		goto Done;
 	} 
 
-	if (privptr->channel[WRITE].free_anchor->block->length + BLOCK_HEADER_LENGTH + PACKET_HEADER_LENGTH + skb->len > 65535) {
+	if (privptr->channel[WRITE].free_anchor->block->length + PACKET_HEADER_LENGTH + skb->len > BLOCK_MAX_DATA) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: early swap\n", dev->name);
 #endif
@@ -1887,15 +1899,14 @@
 		}
 	}
 	
-	if (privptr->channel[WRITE].free_anchor->block->length == 0) {
-		privptr->channel[WRITE].free_anchor->block->length = BLOCK_HEADER_LENGTH; 
+	if (privptr->channel[WRITE].free_anchor->block->length == BLOCK_HEADER_LENGTH) { /* empty block */
 		privptr->channel[WRITE].free_anchor->packets = 0;
 	} 
 
 
 	(__u8 *)lp = (__u8 *) (privptr->channel[WRITE].free_anchor->block) + privptr->channel[WRITE].free_anchor->block->length;
-	privptr->channel[WRITE].free_anchor->block->length += skb->len + PACKET_HEADER_LENGTH;
-	lp->length = skb->len + PACKET_HEADER_LENGTH; 
+	privptr->channel[WRITE].free_anchor->block->length += PACKET_HEADER_LENGTH + skb->len;
+	lp->length = PACKET_HEADER_LENGTH + skb->len; 
 	lp->type = 0x0800; 
 	lp->unused = 0;
 	memcpy(&lp->data, skb->data, skb->len); 

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