case UWB_RSV_STATE_NONE:
                dev_dbg(dev, "removed reservation\n");
                wusbhc_bwa_set(wusbhc, 0, NULL);
-               wusbhc->rsv = NULL;
                break;
        default:
                dev_dbg(dev, "unexpected reservation state: %d\n", rsv->state);
 
 
 /**
- * wusbhc_rsv_terminate - terminate any cluster reservation
+ * wusbhc_rsv_terminate - terminate the cluster reservation
  * @wusbhc: the WUSB host whose reservation is to be terminated
  */
 void wusbhc_rsv_terminate(struct wusbhc *wusbhc)
 {
-       if (wusbhc->rsv)
-               uwb_rsv_terminate(wusbhc->rsv);
+       uwb_rsv_terminate(wusbhc->rsv);
+       uwb_rsv_destroy(wusbhc->rsv);
 }
 
        dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state));
 }
 
+static void uwb_rsv_release(struct kref *kref)
+{
+       struct uwb_rsv *rsv = container_of(kref, struct uwb_rsv, kref);
+
+       kfree(rsv);
+}
+
+static void uwb_rsv_get(struct uwb_rsv *rsv)
+{
+       kref_get(&rsv->kref);
+}
+
+static void uwb_rsv_put(struct uwb_rsv *rsv)
+{
+       kref_put(&rsv->kref, uwb_rsv_release);
+}
+
 /*
  * Get a free stream index for a reservation.
  *
 
        INIT_LIST_HEAD(&rsv->rc_node);
        INIT_LIST_HEAD(&rsv->pal_node);
+       kref_init(&rsv->kref);
        init_timer(&rsv->timer);
        rsv->timer.function = uwb_rsv_timer;
        rsv->timer.data     = (unsigned long)rsv;
        return rsv;
 }
 
-static void uwb_rsv_free(struct uwb_rsv *rsv)
-{
-       uwb_dev_put(rsv->owner);
-       if (rsv->target.type == UWB_RSV_TARGET_DEV)
-               uwb_dev_put(rsv->target.dev);
-       kfree(rsv);
-}
-
 /**
  * uwb_rsv_create - allocate and initialize a UWB reservation structure
  * @rc: the radio controller
        if (rsv->state != UWB_RSV_STATE_NONE)
                uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
        del_timer_sync(&rsv->timer);
-       list_del(&rsv->rc_node);
-       uwb_rsv_free(rsv);
+       uwb_dev_put(rsv->owner);
+       if (rsv->target.type == UWB_RSV_TARGET_DEV)
+               uwb_dev_put(rsv->target.dev);
+
+       list_del_init(&rsv->rc_node);
+       uwb_rsv_put(rsv);
 }
 
 /**
  * uwb_rsv_destroy - free a UWB reservation structure
  * @rsv: the reservation to free
  *
- * The reservation will be terminated if it is pending or established.
+ * The reservation must already be terminated.
  */
 void uwb_rsv_destroy(struct uwb_rsv *rsv)
 {
-       struct uwb_rc *rc = rsv->rc;
-
-       mutex_lock(&rc->rsvs_mutex);
-       uwb_rsv_remove(rsv);
-       mutex_unlock(&rc->rsvs_mutex);
+       uwb_rsv_put(rsv);
 }
 EXPORT_SYMBOL_GPL(uwb_rsv_destroy);
 
                goto out;
        }
 
+       uwb_rsv_get(rsv);
        list_add_tail(&rsv->rc_node, &rc->reservations);
        rsv->owner = &rc->uwb_dev;
        uwb_dev_get(rsv->owner);
  *
  * Reservation requests from peers are denied unless a PAL accepts it
  * by calling this function.
+ *
+ * The PAL call uwb_rsv_destroy() for all accepted reservations before
+ * calling uwb_pal_unregister().
  */
 void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv)
 {
+       uwb_rsv_get(rsv);
+
        rsv->callback = cb;
        rsv->pal_priv = pal_priv;
        rsv->state    = UWB_RSV_STATE_T_ACCEPTED;
 
 
        dev_dbg(dev, "debug: rsv %s -> %s: %s\n",
                owner, target, uwb_rsv_state_str(rsv->state));
+
+       if (rsv->state == UWB_RSV_STATE_NONE) {
+               list_del(&rsv->pal_node);
+               uwb_rsv_destroy(rsv);
+       }
 }
 
 static int cmd_rsv_establish(struct uwb_rc *rc,
                        found = rsv;
                        break;
                }
+               i++;
        }
        if (!found)
                return -EINVAL;
 
-       list_del(&found->pal_node);
        uwb_rsv_terminate(found);
 
        return 0;
 {
        struct uwb_rc *rc = rsv->rc;
 
-       if (rc->dbg->accept)
+       if (rc->dbg->accept) {
+               list_add_tail(&rsv->pal_node, &rc->dbg->rsvs);
                uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, NULL);
+       }
 }
 
 /**
                return;
 
        list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) {
-               uwb_rsv_destroy(rsv);
+               uwb_rsv_terminate(rsv);
        }
 
        uwb_pal_unregister(rc, &rc->dbg->pal);