diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 01:02:30 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 01:02:30 +0000 |
commit | 76cb841cb886eef6b3bee341a2266c76578724ad (patch) | |
tree | f5892e5ba6cc11949952a6ce4ecbe6d516d6ce58 /drivers/usb/wusbcore/reservation.c | |
parent | Initial commit. (diff) | |
download | linux-76cb841cb886eef6b3bee341a2266c76578724ad.tar.xz linux-76cb841cb886eef6b3bee341a2266c76578724ad.zip |
Adding upstream version 4.19.249.upstream/4.19.249
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/usb/wusbcore/reservation.c')
-rw-r--r-- | drivers/usb/wusbcore/reservation.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/drivers/usb/wusbcore/reservation.c b/drivers/usb/wusbcore/reservation.c new file mode 100644 index 000000000..6dcfc6825 --- /dev/null +++ b/drivers/usb/wusbcore/reservation.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * WUSB cluster reservation management + * + * Copyright (C) 2007 Cambridge Silicon Radio Ltd. + */ +#include <linux/kernel.h> +#include <linux/uwb.h> + +#include "wusbhc.h" + +/* + * WUSB cluster reservations are multicast reservations with the + * broadcast cluster ID (BCID) as the target DevAddr. + * + * FIXME: consider adjusting the reservation depending on what devices + * are attached. + */ + +static int wusbhc_bwa_set(struct wusbhc *wusbhc, u8 stream, + const struct uwb_mas_bm *mas) +{ + if (mas == NULL) + mas = &uwb_mas_bm_zero; + return wusbhc->bwa_set(wusbhc, stream, mas); +} + +/** + * wusbhc_rsv_complete_cb - WUSB HC reservation complete callback + * @rsv: the reservation + * + * Either set or clear the HC's view of the reservation. + * + * FIXME: when a reservation is denied the HC should be stopped. + */ +static void wusbhc_rsv_complete_cb(struct uwb_rsv *rsv) +{ + struct wusbhc *wusbhc = rsv->pal_priv; + struct device *dev = wusbhc->dev; + struct uwb_mas_bm mas; + + dev_dbg(dev, "%s: state = %d\n", __func__, rsv->state); + switch (rsv->state) { + case UWB_RSV_STATE_O_ESTABLISHED: + uwb_rsv_get_usable_mas(rsv, &mas); + dev_dbg(dev, "established reservation: %*pb\n", + UWB_NUM_MAS, mas.bm); + wusbhc_bwa_set(wusbhc, rsv->stream, &mas); + break; + case UWB_RSV_STATE_NONE: + dev_dbg(dev, "removed reservation\n"); + wusbhc_bwa_set(wusbhc, 0, NULL); + break; + default: + dev_dbg(dev, "unexpected reservation state: %d\n", rsv->state); + break; + } +} + + +/** + * wusbhc_rsv_establish - establish a reservation for the cluster + * @wusbhc: the WUSB HC requesting a bandwidth reservation + */ +int wusbhc_rsv_establish(struct wusbhc *wusbhc) +{ + struct uwb_rc *rc = wusbhc->uwb_rc; + struct uwb_rsv *rsv; + struct uwb_dev_addr bcid; + int ret; + + if (rc == NULL) + return -ENODEV; + + rsv = uwb_rsv_create(rc, wusbhc_rsv_complete_cb, wusbhc); + if (rsv == NULL) + return -ENOMEM; + + bcid.data[0] = wusbhc->cluster_id; + bcid.data[1] = 0; + + rsv->target.type = UWB_RSV_TARGET_DEVADDR; + rsv->target.devaddr = bcid; + rsv->type = UWB_DRP_TYPE_PRIVATE; + rsv->max_mas = 256; /* try to get as much as possible */ + rsv->min_mas = 15; /* one MAS per zone */ + rsv->max_interval = 1; /* max latency is one zone */ + rsv->is_multicast = true; + + ret = uwb_rsv_establish(rsv); + if (ret == 0) + wusbhc->rsv = rsv; + else + uwb_rsv_destroy(rsv); + return ret; +} + + +/** + * 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_destroy(wusbhc->rsv); + wusbhc->rsv = NULL; + } +} |