static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
 static struct spinlock list_lock;
+static struct most_aim aim;
 
 
 static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
 
        BUG_ON(!nd->tx.linked || !nd->rx.linked);
 
-       if (most_start_channel(nd->iface, nd->rx.ch_id)) {
+       if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
                netdev_err(dev, "most_start_channel() failed\n");
                return -EBUSY;
        }
 
-       if (most_start_channel(nd->iface, nd->tx.ch_id)) {
+       if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) {
                netdev_err(dev, "most_start_channel() failed\n");
-               most_stop_channel(nd->iface, nd->rx.ch_id);
+               most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
                return -EBUSY;
        }
 
        netif_stop_queue(dev);
 
        if (nd->channels_opened) {
-               most_stop_channel(nd->iface, nd->rx.ch_id);
-               most_stop_channel(nd->iface, nd->tx.ch_id);
+               most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
+               most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
                nd->channels_opened = false;
        }
 
 
        atomic_t mbo_nq_level;
        uint16_t channel_id;
        bool is_poisoned;
-       bool is_started;
+       struct mutex start_mutex;
        int is_starving;
        struct most_interface *iface;
        struct most_inst_obj *inst;
        struct list_head list;
        struct most_aim *first_aim;
        struct most_aim *second_aim;
+       int first_aim_refs;
+       int second_aim_refs;
        struct list_head trash_fifo;
        struct task_struct *hdm_enqueue_task;
        struct mutex stop_task_mutex;
        list_add_tail(&mbo->list, &c->fifo);
        spin_unlock_irqrestore(&c->fifo_lock, flags);
 
-       if (c->second_aim && c->second_aim->tx_completion)
-               c->second_aim->tx_completion(c->iface, c->channel_id);
-       if (c->first_aim && c->first_aim->tx_completion)
+       if (c->first_aim_refs && c->first_aim->tx_completion)
                c->first_aim->tx_completion(c->iface, c->channel_id);
+
+       if (c->second_aim_refs && c->second_aim->tx_completion)
+               c->second_aim->tx_completion(c->iface, c->channel_id);
 }
 
 /**
  */
 static void most_read_completion(struct mbo *mbo)
 {
-       struct most_c_obj *c;
+       struct most_c_obj *c = mbo->context;
 
-       c = mbo->context;
-       if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE)))
-               goto release_mbo;
+       if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) {
+               trash_mbo(mbo);
+               return;
+       }
 
        if (mbo->status == MBO_E_INVAL) {
                nq_hdm_mbo(mbo);
                c->is_starving = 1;
        }
 
-       if (c->first_aim && c->first_aim->rx_completion &&
+       if (c->first_aim_refs && c->first_aim->rx_completion &&
            c->first_aim->rx_completion(mbo) == 0)
                return;
-       if (c->second_aim && c->second_aim->rx_completion &&
+
+       if (c->second_aim_refs && c->second_aim->rx_completion &&
            c->second_aim->rx_completion(mbo) == 0)
                return;
-       pr_info("WARN: no driver linked with this channel\n");
-       mbo->status = MBO_E_CLOSE;
-release_mbo:
-       trash_mbo(mbo);
+
+       most_put_mbo(mbo);
 }
 
 /**
  *
  * Returns 0 on success or error code otherwise.
  */
-int most_start_channel(struct most_interface *iface, int id)
+int most_start_channel(struct most_interface *iface, int id,
+                      struct most_aim *aim)
 {
        int num_buffer;
        int ret;
        if (unlikely(!c))
                return -EINVAL;
 
-       if (c->is_started)
-               return -EBUSY;
+       mutex_lock(&c->start_mutex);
+       if (c->first_aim_refs + c->second_aim_refs > 0)
+               goto out; /* already started by other aim */
 
        if (!try_module_get(iface->mod)) {
                pr_info("failed to acquire HDM lock\n");
+               mutex_unlock(&c->start_mutex);
                return -ENOLCK;
        }
        modref++;
        if (ret)
                goto error;
 
-       c->is_started = true;
        c->is_starving = 0;
        atomic_set(&c->mbo_ref, num_buffer);
+
+out:
+       if (aim == c->first_aim)
+               c->first_aim_refs++;
+       if (aim == c->second_aim)
+               c->second_aim_refs++;
+       mutex_unlock(&c->start_mutex);
        return 0;
+
 error:
        if (iface->mod)
                module_put(iface->mod);
        modref--;
+       mutex_unlock(&c->start_mutex);
        return ret;
 }
 EXPORT_SYMBOL_GPL(most_start_channel);
  * @iface: pointer to interface instance
  * @id: channel ID
  */
-int most_stop_channel(struct most_interface *iface, int id)
+int most_stop_channel(struct most_interface *iface, int id,
+                     struct most_aim *aim)
 {
        struct most_c_obj *c;
 
        if (unlikely(!c))
                return -EINVAL;
 
-       if (!c->is_started)
-               return 0;
+       mutex_lock(&c->start_mutex);
+       if (c->first_aim_refs + c->second_aim_refs >= 2)
+               goto out;
 
        mutex_lock(&c->stop_task_mutex);
        if (c->hdm_enqueue_task)
        mutex_lock(&deregister_mutex);
        if (atomic_read(&c->inst->tainted)) {
                mutex_unlock(&deregister_mutex);
+               mutex_unlock(&c->start_mutex);
                return -ENODEV;
        }
        mutex_unlock(&deregister_mutex);
        if (c->iface->poison_channel(c->iface, c->channel_id)) {
                pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id,
                       c->iface->description);
+               mutex_unlock(&c->start_mutex);
                return -EAGAIN;
        }
        flush_trash_fifo(c);
 #ifdef CMPL_INTERRUPTIBLE
        if (wait_for_completion_interruptible(&c->cleanup)) {
                pr_info("Interrupted while clean up ch %d\n", c->channel_id);
+               mutex_unlock(&c->start_mutex);
                return -EINTR;
        }
 #else
        wait_for_completion(&c->cleanup);
 #endif
        c->is_poisoned = false;
-       c->is_started = false;
+
+out:
+       if (aim == c->first_aim)
+               c->first_aim_refs--;
+       if (aim == c->second_aim)
+               c->second_aim_refs--;
+       mutex_unlock(&c->start_mutex);
        return 0;
 }
 EXPORT_SYMBOL_GPL(most_stop_channel);
                c->keep_mbo = false;
                c->enqueue_halt = false;
                c->is_poisoned = false;
-               c->is_started = false;
                c->cfg.direction = 0;
                c->cfg.data_type = 0;
                c->cfg.num_buffers = 0;
                INIT_LIST_HEAD(&c->halt_fifo);
                init_completion(&c->cleanup);
                atomic_set(&c->mbo_ref, 0);
+               mutex_init(&c->start_mutex);
                mutex_init(&c->stop_task_mutex);
                list_add_tail(&c->list, &inst->channel_list);
        }
        }
 
        list_for_each_entry(c, &i->channel_list, list) {
-               if (!c->is_started)
+               if (c->first_aim_refs + c->second_aim_refs <= 0)
                        continue;
 
                mutex_lock(&c->stop_task_mutex);