Ich habe mich jetzt nochmal an den Source gewagt - und wie es scheint
mit Erfolg. Habe jetzt seit ein paar Tagen keine "not on queue" Messages
mehr und ein Hang ist bislang auch noch nicht aufgetreten. Allerdings
bin ich mir nicht sicher ob die Loesung so optimal ist. Ich haenge den
Patch mal an, vielleicht hat ja jemand Lust/Zeit/Knowhow um
drueberzuschauen bzw. ihn zu testen.
Gerade an Karsten haette ich da noch eine Frage zum Codeteil:
#if defined (DRIVER_TYPE_DSL)
- if (ctrl->cnr != card->ctrl2) {
+ if (ctrl->cnr == card->ctrl2) {
return;
}
was auch hier (http://osdir.com/ml/isdn.i4l.user/2005-11/msg00025.html)
besprochen wurde. Ich habe das bei beiden Auftreten im Code entsprechend
gaendert. Allerdings ist mir nicht klar was es bewirkt. Waere da eine
kurze Erklaerung moeglich was die Aenderung bewirkt und ob das in beiden
Faellen sinnvoll ist?
Danke
Karsten Keil schrieb:
On Wed, Jul 30, 2008 at 09:57:39AM +0200, Fabian Urhausen wrote:
Danke fuer deine Bestaetigung. Habe das Problem mittlerweile jetzt
schon von mehreren Personen bestaetigt bekommen. Es wundert mich nur
das es (scheinbar) bislang keinen gestoehrt hat und man auch sonst zu
dem Thema nichts findet.
Das Problem ist, das der core des Treibers nur binary only vorliegt,
damit kann man leider solche Sachen schlecht untersuchen und fixen.
Bitte lasst die Betroffenen nicht dumm sterben. Keiner eine Idee oder
einen Hinweis?
Eventuell bringt eine Portierung der erwähnten Patches etwas, aber sicher
ist das nicht, die Sachen die das zusaetzliche locking brauchen, sind im
open source Teil.
diff -NurpP --minimal fritz/src/common.h fritz.patched/src/common.h
--- fritz/src/common.h 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/common.h 2008-08-07 11:12:32.332267907 +0200
@@ -44,7 +44,6 @@ typedef unsigned (__attr * xfer_func_t)
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
typedef long intptr_t;
-typedef unsigned long uintptr_t;
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
diff -NurpP --minimal fritz/src/devif.c fritz.patched/src/devif.c
--- fritz/src/devif.c 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/devif.c 2008-08-07 11:12:32.336268487 +0200
@@ -233,7 +233,7 @@ int dma_setup (dma_struct_p pdma, unsign
assert (buf_size > 0);
assert (pdma != NULL);
assert (pdma->virt_addr == 0UL);
- if (NULL == (buf1 = kmalloc (buf_size + DMA_ALIGNMENT, GFP_ATOMIC))) {
+ if (NULL == (buf1 = kmalloc (buf_size + DMA_ALIGNMENT, GFP_DMA | GFP_ATOMIC))) {
pdma->virt_addr = 0UL;
return FALSE;
}
@@ -748,12 +748,11 @@ static void xfer_task (unsigned long dat
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
-irqreturn_t device_interrupt (int irq, void * args, struct pt_regs * regs) {
+irqreturn_t device_interrupt (int irq, void * args) {
unsigned long intpins;
card_p cp = (card_p) args;
UNUSED_ARG (irq);
- UNUSED_ARG (regs);
assert (capi_card == cp);
intpins = PINL (cp->mmio_base + C6205_PCI_HSR_OFFSET);
diff -NurpP --minimal fritz/src/devif.h fritz.patched/src/devif.h
--- fritz/src/devif.h 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/devif.h 2008-08-07 11:12:32.336268487 +0200
@@ -80,7 +80,7 @@ extern __attr void dif_xfer_requirements
extern void set_interrupt_callback (irq_callback_t, void *);
extern void clear_interrupt_callback (void);
-extern irqreturn_t device_interrupt (int, void *, struct pt_regs *);
+extern irqreturn_t device_interrupt (int, void *);
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
diff -NurpP --minimal fritz/src/driver.c fritz.patched/src/driver.c
--- fritz/src/driver.c 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/driver.c 2008-08-07 11:12:32.336268487 +0200
@@ -18,6 +18,10 @@
* http://www.opensource.org/licenses/lgpl-license.html
*
* Contact: AVM GmbH, Alt-Moabit 95, 10559 Berlin, Germany, email: info@avm.de
+ *
+ * Thu Aug 7 11:08:10 2008
+ * Modified by Fabian Urhausen to fix freezes and improve locking
+ * For more questions contact me at fabian@hostbone.eu
*/
#include
@@ -56,6 +60,8 @@
#include "devif.h"
#include "driver.h"
+#undef SINGLE_LOCK
+
#define KILOBYTE 1024
#define MEGABYTE (1024*KILOBYTE)
#define _2_MEGS_ (2*MEGABYTE)
@@ -117,7 +123,7 @@ static DECLARE_WAIT_QUEUE_HEAD(wait);
static DECLARE_WAIT_QUEUE_HEAD(capi_wait);
static DECLARE_WAIT_QUEUE_HEAD(dbg_wait);
-static DECLARE_MUTEX_LOCKED(thread_sync);
+static DECLARE_COMPLETION(thread_sync);
#define SCHED_WAKEUP_CAPI { atomic_set (&thread_capi_flag, 1); wake_up_interruptible (&capi_wait); }
#define SCHED_WAKEUP { atomic_set (&got_kicked, 1); wake_up_interruptible (&wait); }
@@ -488,7 +494,7 @@ int start (card_p cp) {
res = request_irq (
cp->irq,
&device_interrupt,
- SA_INTERRUPT | SA_SHIRQ,
+ IRQF_DISABLED | IRQF_SHARED,
TARGET,
cp
);
@@ -1023,8 +1029,9 @@ static void __kcapi reset_ctrl (struct c
if (cp->appls != NULL) {
appp = first_appl (cp->appls);
while (appp != NULL) {
+ appl_t *next_appp = next_appl (cp->appls, appp);
free_ncci (appp->id, (unsigned) -1);
- appp = next_appl (cp->appls, appp);
+ appp = next_appp;
}
}
}
@@ -1270,7 +1277,6 @@ int msg2stack (unsigned char * msg) {
queue_park (capi_card->queue, skb, appl, ncci, hand);
} else {
lib_memcpy (msg, mptr, mlen);
- assert (skb->list == NULL);
kfree_skb (skb);
}
}
@@ -1361,6 +1367,7 @@ void msg2capi (unsigned char * msg) {
/*-S-------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
static int sched_thread (void * arg) {
+ unsigned long flags;
UNUSED_ARG (arg);
daemonize (TARGET);
@@ -1396,6 +1403,7 @@ static int sched_thread (void * arg) {
}
/* Body of thread, invoke scheduler */
+ local_irq_save(flags);
if (!test_and_set_bit (0, &stack_lock)) {
os_timer_poll ();
assert (capi_lib->cm_schedule);
@@ -1404,9 +1412,10 @@ static int sched_thread (void * arg) {
}
clear_bit (0, &stack_lock);
}
+ local_irq_restore(flags);
}
LOG("Scheduler thread stopped.\n");
- up (&thread_sync);
+ complete(&thread_sync);
return 0;
} /* sched_thread */
@@ -1440,7 +1449,7 @@ static void kill_thread (void) {
SCHED_WAKEUP;
}
LOG("Thread signalled, waiting for termination...\n");
- down (&thread_sync);
+ wait_for_completion(&thread_sync);
LOG("Thread[%d] terminated.\n", thread_pid);
}
thread_pid = -1;
@@ -1564,19 +1573,19 @@ void __stack init (unsigned len, void (_
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
-int driver_init (void) {
+int avm_driver_init (void) {
return (NULL != (capi_lib = link_library (&capi_card)));
-} /* driver_init */
+} /* avm_driver_init */
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
-void driver_exit (void) {
+void avm_driver_exit (void) {
assert (capi_lib);
free_library ();
capi_lib = NULL;
-} /* driver_exit */
+} /* avm_driver_exit */
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
diff -NurpP --minimal fritz/src/driver.h fritz.patched/src/driver.h
--- fritz/src/driver.h 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/driver.h 2008-08-07 11:12:32.336268487 +0200
@@ -24,7 +24,7 @@
#define __have_driver_h__
#include
-#include
+#include
#include
#include
#include
@@ -161,8 +161,8 @@ extern void init (unsigned, void (__attr
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
-extern int driver_init (void);
-extern void driver_exit (void);
+extern int avm_driver_init (void);
+extern void avm_driver_exit (void);
#endif
diff -NurpP --minimal fritz/src/main.c fritz.patched/src/main.c
--- fritz/src/main.c 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/main.c 2008-08-07 11:12:32.336268487 +0200
@@ -23,7 +23,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -116,14 +116,14 @@ static int __devinit fcdsl2_probe (
return -ENODEV;
}
NOTE("Loading...\n");
- if (!driver_init ()) {
+ if (!avm_driver_init ()) {
ERROR("Error: Driver library not available.\n");
NOTE("Not loaded.\n");
return -ENOSYS;
}
if (0 != (res = add_card (dev))) {
NOTE("Not loaded.\n");
- driver_exit ();
+ avm_driver_exit ();
return res;
}
NOTE("Loaded.\n");
@@ -144,7 +144,7 @@ static void __devexit fcdsl2_remove (str
NOTE("Removing...\n");
remove_ctrls (cp);
NOTE("Removed.\n");
- driver_exit ();
+ avm_driver_exit ();
#ifndef NDEBUG
if (hallocated() != 0) {
ERROR("%u bytes leaked.\n", hallocated());
@@ -195,7 +195,7 @@ static int __init fcdsl2_init (void) {
NOTE("-- 32 bit CAPI driver --\n");
#endif
- if (0 == (err = pci_module_init (&fcdsl2_driver))) {
+ if (0 == (err = pci_register_driver (&fcdsl2_driver))) {
LOG("PCI driver registered.\n");
register_capi_driver (&fcdsl2_capi_driver);
LOG("CAPI driver registered.\n");
diff -NurpP --minimal fritz/src/Makefile fritz.patched/src/Makefile
--- fritz/src/Makefile 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/Makefile 2008-08-07 11:12:32.336268487 +0200
@@ -12,7 +12,7 @@ EXTRA_CFLAGS += -D__$(CARD)__ -DTARGET=\
ifndef DEBUG
EXTRA_CFLAGS += -DNDEBUG
endif
-EXTRA_LDFLAGS += $(LIBDIR)/$(CARD)-lib.o
+EXTRA_LDFLAGS += $(LIBDIR)/$(CARD)-lib.o -d
obj-m := $(CARD).o
$(CARD)-objs := $(OBJECTS)
diff -NurpP --minimal fritz/src/queue.c fritz.patched/src/queue.c
--- fritz/src/queue.c 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/queue.c 2008-08-07 11:12:32.336268487 +0200
@@ -30,7 +30,7 @@
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
-#define MAKE_KEY(a,n,h) (((tag_t)(a)<<48)+((tag_t)(n)<<16)+((tag_t)(h)))
+#define MAKE_KEY(a,n,h) (((avm_tag_t)(a)<<48)+((avm_tag_t)(n)<<16)+((avm_tag_t)(h)))
#define IS_EMPTY(q) ((q)->get==NULL)
/*---------------------------------------------------------------------------*\
@@ -79,14 +79,12 @@ void queue_exit (queue_t ** q) {
assert (*q != NULL);
while ((*q)->get != NULL) {
item = (*q)->get->succ;
- assert ((*q)->get->msg->list == NULL);
kfree_skb ((*q)->get->msg);
hfree ((*q)->get);
(*q)->get = item;
}
while ((*q)->noconf != NULL) {
item = (*q)->noconf->succ;
- assert ((*q)->noconf->msg->list == NULL);
kfree_skb ((*q)->noconf->msg);
hfree ((*q)->noconf);
(*q)->noconf = item;
@@ -108,7 +106,6 @@ static int enqueue (queue_t * q, struct
assert (q != NULL);
assert (msg != NULL);
- assert (msg->list == NULL);
if (NULL == (item = alloc_item ())) {
ERROR("Not enough memory for queue item.\n");
ERROR("Message lost.\n");
@@ -141,7 +138,6 @@ static struct sk_buff * dequeue (queue_t
tmp = q->get;
q->get = item;
free_item (tmp);
- assert (res->list == NULL);
return res;
} /* dequeue */
@@ -215,7 +211,7 @@ void queue_park (
\*---------------------------------------------------------------------------*/
void queue_conf (queue_t * q, unsigned appl, NCCI_t ncci, unsigned hand) {
qitem_t * item;
- tag_t key = MAKE_KEY (appl, ncci, hand);
+ avm_tag_t key = MAKE_KEY (appl, ncci, hand);
struct sk_buff * tmp = NULL;
assert (q != NULL);
@@ -241,7 +237,6 @@ void queue_conf (queue_t * q, unsigned a
}
unlock (q->lock);
if (tmp != NULL) {
- assert (tmp->list == NULL);
kfree_skb (tmp);
}
} /* queue_conf */
diff -NurpP --minimal fritz/src/queue.h fritz.patched/src/queue.h
--- fritz/src/queue.h 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/queue.h 2008-08-07 11:12:32.336268487 +0200
@@ -29,14 +29,14 @@
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
-typedef long long tag_t;
+typedef long long avm_tag_t;
typedef __u32 NCCI_t;
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
typedef struct __qitem {
- tag_t key;
+ avm_tag_t key;
struct sk_buff * msg;
struct __qitem * succ;
struct __qitem * pred;
diff -NurpP --minimal fritz/src/tables.c fritz.patched/src/tables.c
--- fritz/src/tables.c 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/tables.c 2008-08-07 16:35:03.240267776 +0200
@@ -96,7 +96,9 @@ static void remove_appl (appltab_t * tab
remove_ncci (tab, appp, nccip);
nccip = tmp;
}
+ lock (capi_card->appls->lock);
capilib_release_appl (&tab->ncci_head, appp->id);
+ unlock (capi_card->appls->lock);
hfree (appp);
} /* remove_appl */
@@ -234,6 +236,7 @@ static capiinfo_t handle_message (
ci = CAPI_ILLAPPNR;
goto done;
}
+ lock (capi_card->appls->lock);
switch (CAPIMSG_CMD(msg->data)) {
case CAPI_DATA_B3_REQ:
@@ -258,6 +261,7 @@ static capiinfo_t handle_message (
}
}
done:
+ unlock (capi_card->appls->lock);
return ci;
} /* handle_message */
@@ -267,6 +271,7 @@ capiinfo_t handle_data_conf (appltab_t *
unsigned appl, hand;
NCCI_t ncci;
+ lock (capi_card->appls->lock);
assert (tab != NULL);
assert (q != NULL);
assert (m != NULL);
@@ -276,6 +281,7 @@ capiinfo_t handle_data_conf (appltab_t *
hand = CAPIMSG_U16(m, 12);
queue_conf (q, appl, ncci, hand);
capilib_data_b3_conf (&tab->ncci_head, appl, ncci, CAPIMSG_MSGID(m));
+ unlock (capi_card->appls->lock);
return CAPI_NOERROR;
} /* handle_data_conf */
@@ -303,7 +309,9 @@ static ncci_t * create_ncci (
return NULL;
}
LOG("New NCCI(%x), window size %u...\n", ncci, wsize);
+ lock (capi_card->appls->lock);
capilib_new_ncci (&tab->ncci_head, appp->id, ncci, wsize);
+ unlock (capi_card->appls->lock);
tmp->ncci = ncci;
tmp->appl = appp->id;
tmp->win_size = wsize;
@@ -330,7 +338,9 @@ void remove_ncci (appltab_t * tab, appl_
assert (nccip);
if (nccip != NULL) {
LOG("Remove NCCI(%x), appl %u...\n", nccip->ncci, appp->id);
+ lock (capi_card->appls->lock);
capilib_free_ncci (&tab->ncci_head, appp->id, nccip->ncci);
+ unlock (capi_card->appls->lock);
lock (tab->lock);
for (i = 0; i < appp->blk_count; i++) {
if (nccip->data[i] != NULL) {
@@ -554,7 +564,7 @@ void __kcapi release_appl (struct capi_c
assert (ctrl != NULL);
card = GET_CARD(ctrl);
#if defined (DRIVER_TYPE_DSL)
- if (ctrl->cnr != card->ctrl2) {
+ if (ctrl->cnr == card->ctrl2) {
return;
}
#endif
@@ -580,7 +590,6 @@ u16 __kcapi send_msg (struct capi_ctr *
assert (ctrl != NULL);
assert (skb != NULL);
- assert (skb->list == NULL);
card = GET_CARD(ctrl);
ci = handle_message (card->appls, card->queue, skb);
kick_scheduler ();
@@ -605,7 +614,7 @@ void __kcapi register_appl (
assert (args != NULL);
card = GET_CARD(ctrl);
#if defined (DRIVER_TYPE_DSL)
- if (ctrl->cnr != card->ctrl2) {
+ if (ctrl->cnr == card->ctrl2) {
return;
}
#endif
diff -NurpP --minimal fritz/src/tools.c fritz.patched/src/tools.c
--- fritz/src/tools.c 2006-01-05 00:00:00.000000000 +0100
+++ fritz.patched/src/tools.c 2008-08-07 11:12:32.336268487 +0200
@@ -110,7 +110,11 @@ static unsigned lib_heap_size = 0;
#define FENCE2_OK(h,m) (*(unsigned *)(((char *) m)+(h)->size)==FENCE_TAG)
static unsigned alloc_count = 0;
+#if defined (SINGLE_LOCK)
+# define track_lock qt_lock
+#else
static spinlock_t track_lock = SPIN_LOCK_UNLOCKED;
+#endif
#if !defined (NDEBUG) && defined (LOG_TIMER)
static struct timeval zero_time;