linux-avmb1:BUGFIX: several capi oops and strange messages in 2.6

Carsten Paeth calle at calle.in-berlin.de
Thu Aug 26 18:45:01 CEST 2004


Hello.

There are several oops with capi in 2.6 kernels:
- oops in skb_dequeue under heavy data load
- kernel message: "BUG: dst underflow 0: xxxxxxx"
- kernel message: "BUG: dst underflow 0: xxxxxxx at xxxxxxx"
- problems with chan_capi and asterisk and AVM cards

The problem is that the low level send_message function in 
the capi hardware drivers free the skb when an error occured.
This is wrong. This bug is in the kernel since transfering
the handling of msgidqueue from kcapi.c to the low level
hardware drivers.

!!!! The skb should only be consumed when CAPI_NOERROR is returned !!!!

The attached patch fixes all that problems.

best regards,

calle

P.S.: Who will schedule this patch to be included in the next version of 2.6 ?
-------------- next part --------------
diff -ru drivers/isdn.old/capi/capidrv.c drivers/isdn/capi/capidrv.c
--- drivers/isdn.old/capi/capidrv.c	2004-08-14 12:55:20.000000000 +0200
+++ drivers/isdn/capi/capidrv.c	2004-08-26 18:00:56.000000000 +0200
@@ -512,7 +512,8 @@
 	len = CAPIMSG_LEN(cmsg->buf);
 	skb = alloc_skb(len, GFP_ATOMIC);
 	memcpy(skb_put(skb, len), cmsg->buf, len);
-	capi20_put_message(&global.ap, skb);
+	if (capi20_put_message(&global.ap, skb) != CAPI_NO_ERROR)
+		kfree_skb(skb);
 }
 
 /* -------- state machine -------------------------------------------- */
diff -ru drivers/isdn.old/hardware/avm/b1.c drivers/isdn/hardware/avm/b1.c
--- drivers/isdn.old/hardware/avm/b1.c	2004-08-26 17:51:50.000000000 +0200
+++ drivers/isdn/hardware/avm/b1.c	2004-08-26 17:55:06.000000000 +0200
@@ -389,7 +389,7 @@
 					     CAPIMSG_NCCI(skb->data),
 					     CAPIMSG_MSGID(skb->data));
 		if (retval != CAPI_NOERROR) 
-			goto out;
+			return retval;
 
 		dlen = CAPIMSG_DATALEN(skb->data);
 
@@ -399,16 +399,14 @@
 		b1_put_slice(port, skb->data + len, dlen);
 		spin_unlock_irqrestore(&card->lock, flags);
 	} else {
-		retval = CAPI_NOERROR;
-
 	 	spin_lock_irqsave(&card->lock, flags);
 		b1_put_byte(port, SEND_MESSAGE);
 		b1_put_slice(port, skb->data, len);
 		spin_unlock_irqrestore(&card->lock, flags);
 	}
- out:
+
 	dev_kfree_skb_any(skb);
-	return retval;
+	return CAPI_NOERROR;
 }
 
 /* ------------------------------------------------------------- */
diff -ru drivers/isdn.old/hardware/avm/b1dma.c drivers/isdn/hardware/avm/b1dma.c
--- drivers/isdn.old/hardware/avm/b1dma.c	2004-08-26 17:51:50.000000000 +0200
+++ drivers/isdn/hardware/avm/b1dma.c	2004-08-26 17:53:43.000000000 +0200
@@ -839,8 +839,6 @@
 	}
 	if (retval == CAPI_NOERROR) 
 		b1dma_queue_tx(card, skb);
-	else
-		dev_kfree_skb_any(skb);
 
 	return retval;
 }
diff -ru drivers/isdn.old/hardware/avm/c4.c drivers/isdn/hardware/avm/c4.c
--- drivers/isdn.old/hardware/avm/c4.c	2004-08-26 17:51:50.000000000 +0200
+++ drivers/isdn/hardware/avm/c4.c	2004-08-26 17:54:04.000000000 +0200
@@ -1029,8 +1029,6 @@
 		spin_lock_irqsave(&card->lock, flags);
 		c4_dispatch_tx(card);
 		spin_unlock_irqrestore(&card->lock, flags);
-	} else {
-		dev_kfree_skb_any(skb);
 	}
 	return retval;
 }
diff -ru drivers/isdn.old/hardware/avm/t1isa.c drivers/isdn/hardware/avm/t1isa.c
--- drivers/isdn.old/hardware/avm/t1isa.c	2004-08-26 17:51:50.000000000 +0200
+++ drivers/isdn/hardware/avm/t1isa.c	2004-08-26 17:54:48.000000000 +0200
@@ -472,7 +472,7 @@
 					     CAPIMSG_NCCI(skb->data),
 					     CAPIMSG_MSGID(skb->data));
 		if (retval != CAPI_NOERROR) 
-			goto out;
+			return retval;
 
 		dlen = CAPIMSG_DATALEN(skb->data);
 
@@ -482,16 +482,15 @@
 		t1_put_slice(port, skb->data + len, dlen);
 		spin_unlock_irqrestore(&card->lock, flags);
 	} else {
-		retval = CAPI_NOERROR;
 
 		spin_lock_irqsave(&card->lock, flags);
 		b1_put_byte(port, SEND_MESSAGE);
 		t1_put_slice(port, skb->data, len);
 		spin_unlock_irqrestore(&card->lock, flags);
 	}
- out:
+
 	dev_kfree_skb_any(skb);
-	return retval;
+	return CAPI_NOERROR;
 }
 /* ------------------------------------------------------------- */
 
diff -ru drivers/isdn.old/hardware/eicon/capifunc.c drivers/isdn/hardware/eicon/capifunc.c
--- drivers/isdn.old/hardware/eicon/capifunc.c	2004-08-14 12:56:01.000000000 +0200
+++ drivers/isdn/hardware/eicon/capifunc.c	2004-08-26 18:03:50.000000000 +0200
@@ -998,7 +998,8 @@
 
       write_end:
 	diva_os_leave_spin_lock(&api_lock, &old_irql, "send message");
-	diva_os_free_message_buffer(dmb);
+	if (retval != CAPI_NOERROR)
+		diva_os_free_message_buffer(dmb);
 	return retval;
 }
 


More information about the linux-avmb1 mailing list