Index: /soft/giet_vm/giet_drivers/mwr_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/mwr_driver.c	(revision 553)
+++ /soft/giet_vm/giet_drivers/mwr_driver.c	(revision 554)
@@ -10,4 +10,5 @@
 #include <mapping_info.h>
 #include <mwr_driver.h>
+#include <ctx_handler.h>
 #include <utils.h>
 #include <kernel_locks.h>
@@ -41,12 +42,30 @@
 
 /////////////////////////////////////////////////////////////////////////////
-//      Global variables
-/////////////////////////////////////////////////////////////////////////////
-
+//      Global variables (all arrays are indexed by the cluster index)
+/////////////////////////////////////////////////////////////////////////////
+
+// Lock protecting exclusive access
 __attribute__((section(".kdata")))
 simple_lock_t  _coproc_lock[X_SIZE*Y_SIZE];
 
-__attribute__((section(".kdata")))
-unsigned int   _coproc_done[X_SIZE*Y_SIZE];
+// Coprocessor type
+__attribute__((section(".kdata")))
+unsigned int  _coproc_type[X_SIZE*Y_SIZE];
+
+// coprocessor characteristics
+__attribute__((section(".kdata")))
+unsigned int   _coproc_info[X_SIZE*Y_SIZE];
+
+// Coprocessor running mode
+__attribute__((section(".kdata")))
+unsigned int  _coproc_mode[X_SIZE*Y_SIZE];
+
+// coprocessor status (for MODE_DMA_IRQ)
+__attribute__((section(".kdata")))
+unsigned int   _coproc_error[X_SIZE*Y_SIZE];
+
+// descheduled task gtid (for MODE_DMA_IRQ)
+__attribute__((section(".kdata")))
+unsigned int   _coproc_gtid[X_SIZE*Y_SIZE];
 
 /////////////////////////////////////////////////////////////////////////////
@@ -93,5 +112,5 @@
         SEG_MWR_BASE + 
         (cluster_xy * PERI_CLUSTER_INCREMENT) + 
-        ((channel + 1) * (CHANNEL_SPAN << 2)) +
+        ((channel + 1) * (MWR_CHANNEL_SPAN << 2)) +
         (index << 2);
 
@@ -103,5 +122,5 @@
 // defined by the "index" and "channel") arguments, in the MWMR_DMA component
 // contained in cluster "cluster_xy".
-/////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////yy
 void _mwr_set_channel_register( unsigned int cluster_xy,  // cluster index
                                 unsigned int channel,     // channel index
@@ -112,5 +131,5 @@
         SEG_MWR_BASE + 
         (cluster_xy * PERI_CLUSTER_INCREMENT) +
-        ((channel + 1) * (CHANNEL_SPAN << 2)) +
+        ((channel + 1) * (MWR_CHANNEL_SPAN << 2)) +
         (index << 2);
         
@@ -118,22 +137,92 @@
 }
 
-///////////////////////////////////////////////////////
-void _mwr_isr( unsigned int irq_type,  // should be HWI 
+////////////////////////////////////////////////////////////////////////////yy
+// This Interrupt service routine is called in two situations:
+// - The MWR_DMA component is running in MODE_DMA_IRQ, and all the
+//   communication channels have successfully completed.
+// - The MWR_DMA component is running in any mode, and at least one
+//   communication channel is reporting a VCI error.
+////////////////////////////////////////////////////////////////////////////yy
+void _mwr_isr( unsigned int irq_type,  // unused : should be HWI 
                unsigned int irq_id,    // index returned by XCU
-               unsigned int channel )  // MWMR_DMA channel
-{
+               unsigned int bloup )    // unused : should be 0          
+{
+    // get coprocessor coordinates and characteristics
+    // the processor executing the ISR an the coprocessor
+    // are in the same cluster
     unsigned int gpid       = _get_procid();
     unsigned int cluster_xy = gpid >> P_WIDTH;
     unsigned int x          = cluster_xy >> Y_WIDTH;
     unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
-
-    // acknowledge IRQ
-    _mwr_set_channel_register( cluster_xy, channel, CHANNEL_RUNNING, 0 );
-
-    // compute coproc_id from cluster coordinates
-    unsigned int coproc_id = x * Y_SIZE + y;
-
-    // set synchronisation variable
-    _coproc_done[coproc_id] = 1;
+    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
+    unsigned int cluster_id = x * Y_SIZE + y;
+    unsigned int info       = _coproc_info[cluster_id];
+    unsigned int nb_to      = info & 0xFF;
+    unsigned int nb_from    = (info>>8) & 0xFF;
+    unsigned int channel;
+    unsigned int status;
+    unsigned int error = 0;
+
+    // check status, report errors and reset all channels
+    for ( channel = 0 ; channel < (nb_to + nb_from) ; channel++ )
+    {
+        status = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_STATUS );
+
+        if ( status == MWR_CHANNEL_BUSY )          // strange => report error
+        {
+            _printf("\n[GIET_ERROR] in _mwr_isr() : channel %d is busy\n", channel );
+            error = 1;
+        }
+        else if ( status == MWR_CHANNEL_ERROR_DATA ) 
+        {
+            _printf("\n[GIET_ERROR] in _mwr_isr() : DATA_ERROR / channel %d\n", channel );
+            error = 1;
+        }
+        else if ( status == MWR_CHANNEL_ERROR_LOCK )
+        {
+            _printf("\n[GIET_ERROR] in _mwr_isr() : LOCK_ERROR / channel %d\n", channel );
+            error = 1;
+        }
+        else if ( status == MWR_CHANNEL_ERROR_DESC )
+        {
+            _printf("\n[GIET_ERROR] in _mwr_isr() : DESC_ERROR / channel %d\n", channel );
+            error = 1;
+        }
+
+        // reset channel
+        _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 0 ); 
+    }
+
+    // register error
+    _coproc_error[cluster_id]  = error;
+
+    // identify task waiting on coprocessor completion
+    // this task can run in a remote cluster 
+    unsigned int gtid           = _coproc_gtid[cluster_id];
+    unsigned int remote_procid  = gtid>>16;
+    unsigned int ltid           = gtid & 0xFFFF;
+    unsigned int remote_cluster = remote_procid >> P_WIDTH;
+    unsigned int remote_x       = remote_cluster >> Y_WIDTH;
+    unsigned int remote_y       = remote_cluster & ((1<<Y_WIDTH)-1);
+    unsigned int remote_p       = remote_procid & ((1<<P_WIDTH)-1);
+
+    // re-activates sleeping task
+    _set_task_slot( remote_x,
+                    remote_y,
+                    remote_p,
+                    ltid,        
+                    CTX_RUN_ID,  // CTX_RUN slot 
+                    1 );         // running value
+
+    // send a WAKUP WTI to processor running the sleeping task 
+    _xcu_send_wti( remote_cluster,   
+                   remote_p, 
+                   0 );          // don't force context switch 
+
+#if GIET_DEBUG_COPROC  
+_printf("\n[GIET DEBUG COPROC] P[%d,%d,%d] executes _mwr_isr() at cycle %d\n"
+        "  for task %d running on P[%d,%d,%d] / error = %d\n",
+        x , y , p , _get_proctime() , ltid , remote_x , remote_y , remote_p , error );
+#endif
 }
 
Index: /soft/giet_vm/giet_drivers/mwr_driver.h
===================================================================
--- /soft/giet_vm/giet_drivers/mwr_driver.h	(revision 553)
+++ /soft/giet_vm/giet_drivers/mwr_driver.h	(revision 554)
@@ -36,18 +36,27 @@
 enum MwmrDmaRegisters 
 {
-    CHANNEL_BUFFER_LSB   = 0,     // Data buffer paddr 32 LSB bits
-    CHANNEL_BUFFER_MSB   = 1,     // Data buffer paddr extension
-    CHANNEL_MWMR_LSB     = 2,     // MWMR descriptor paddr 32 LSB bits
-    CHANNEL_MWMR_MSB     = 3,     // MWMR descriptor paddr extension
-    CHANNEL_LOCK_LSB     = 4,     // MWMR lock paddr 32 LSB bits
-    CHANNEL_LOCK_MSB     = 5,     // MWMR lock paddr extension
-    CHANNEL_WAY          = 6,     // TO_COPROC / FROMCOPROC         (Read-only)
-    CHANNEL_MODE         = 7,     // MWMR / DMA / DMA_IRQ 
-    CHANNEL_SIZE         = 8,     // Data Buffer size (bytes)
-    CHANNEL_RUNNING      = 9,     // channel running   
-    CHANNEL_STATUS       = 10,    // channel FSM state              (Read-Only)
-    CHANNEL_INFO         = 11,    // STS | CFG | FROM | TO          (Read-Only)
+    MWR_CHANNEL_BUFFER_LSB   = 0,     // Data buffer paddr 32 LSB bits
+    MWR_CHANNEL_BUFFER_MSB   = 1,     // Data buffer paddr extension
+    MWR_CHANNEL_MWMR_LSB     = 2,     // MWMR descriptor paddr 32 LSB bits
+    MWR_CHANNEL_MWMR_MSB     = 3,     // MWMR descriptor paddr extension
+    MWR_CHANNEL_LOCK_LSB     = 4,     // MWMR lock paddr 32 LSB bits
+    MWR_CHANNEL_LOCK_MSB     = 5,     // MWMR lock paddr extension
+    MWR_CHANNEL_WAY          = 6,     // TO_COPROC / FROMCOPROC         (Read-only)
+    MWR_CHANNEL_MODE         = 7,     // MWMR / DMA / DMA_IRQ 
+    MWR_CHANNEL_SIZE         = 8,     // Data Buffer size (bytes)
+    MWR_CHANNEL_RUNNING      = 9,     // channel running   
+    MWR_CHANNEL_STATUS       = 10,    // channel FSM state              (Read-Only)
+    MWR_CHANNEL_INFO         = 11,    // STS | CFG | FROM | TO          (Read-Only)
     //
-    CHANNEL_SPAN         = 16,
+    MWR_CHANNEL_SPAN         = 16,
+};
+
+enum MwrDmaStatus
+{
+    MWR_CHANNEL_SUCCESS    = 0,
+    MWR_CHANNEL_ERROR_DATA = 1,
+    MWR_CHANNEL_ERROR_LOCK = 2,
+    MWR_CHANNEL_ERROR_DESC = 3,
+    MWR_CHANNEL_BUSY       = 4,
 };
 
