18cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel/*
28cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * UWB DRP IE management.
38cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel *
48cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * Copyright (C) 2005-2006 Intel Corporation
58cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
68cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel *
78cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * This program is free software; you can redistribute it and/or
88cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * modify it under the terms of the GNU General Public License version
98cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * 2 as published by the Free Software Foundation.
108cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel *
118cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * This program is distributed in the hope that it will be useful,
128cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * but WITHOUT ANY WARRANTY; without even the implied warranty of
138cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
148cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * GNU General Public License for more details.
158cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel *
168cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * You should have received a copy of the GNU General Public License
178cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * along with this program.  If not, see <http://www.gnu.org/licenses/>.
188cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel */
198cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel#include <linux/kernel.h>
208cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel#include <linux/random.h>
215a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
228cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel#include <linux/uwb.h>
238cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
248cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel#include "uwb-internal.h"
258cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
265b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
275b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella/*
285b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella * Return the reason code for a reservations's DRP IE.
295b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella */
305b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panellaint uwb_rsv_reason_code(struct uwb_rsv *rsv)
315b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella{
325b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	static const int reason_codes[] = {
335b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_INITIATED]          = UWB_DRP_REASON_ACCEPTED,
345b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_PENDING]            = UWB_DRP_REASON_ACCEPTED,
355b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_MODIFIED]           = UWB_DRP_REASON_MODIFIED,
365b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_ESTABLISHED]        = UWB_DRP_REASON_ACCEPTED,
375b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_TO_BE_MOVED]        = UWB_DRP_REASON_ACCEPTED,
385b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_MOVE_COMBINING]     = UWB_DRP_REASON_MODIFIED,
395b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_MOVE_REDUCING]      = UWB_DRP_REASON_MODIFIED,
405b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_MOVE_EXPANDING]     = UWB_DRP_REASON_ACCEPTED,
415b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_ACCEPTED]           = UWB_DRP_REASON_ACCEPTED,
425b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_CONFLICT]           = UWB_DRP_REASON_CONFLICT,
435b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_PENDING]            = UWB_DRP_REASON_PENDING,
445b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_DENIED]             = UWB_DRP_REASON_DENIED,
455b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_RESIZED]            = UWB_DRP_REASON_ACCEPTED,
465b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = UWB_DRP_REASON_ACCEPTED,
475b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_CONFLICT] = UWB_DRP_REASON_CONFLICT,
485b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_PENDING]  = UWB_DRP_REASON_PENDING,
495b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_DENIED]   = UWB_DRP_REASON_DENIED,
505b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	};
515b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
525b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	return reason_codes[rsv->state];
535b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella}
545b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
555b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella/*
565b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella * Return the reason code for a reservations's companion DRP IE .
575b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella */
585b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panellaint uwb_rsv_companion_reason_code(struct uwb_rsv *rsv)
595b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella{
605b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	static const int companion_reason_codes[] = {
615b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_MOVE_EXPANDING]     = UWB_DRP_REASON_ACCEPTED,
625b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = UWB_DRP_REASON_ACCEPTED,
635b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_CONFLICT] = UWB_DRP_REASON_CONFLICT,
645b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_PENDING]  = UWB_DRP_REASON_PENDING,
655b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_DENIED]   = UWB_DRP_REASON_DENIED,
665b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	};
675b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
685b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	return companion_reason_codes[rsv->state];
695b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella}
705b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
715b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella/*
725b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella * Return the status bit for a reservations's DRP IE.
735b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella */
745b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panellaint uwb_rsv_status(struct uwb_rsv *rsv)
755b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella{
765b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	static const int statuses[] = {
775b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_INITIATED]          = 0,
785b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_PENDING]            = 0,
795b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_MODIFIED]           = 1,
805b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_ESTABLISHED]        = 1,
815b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_TO_BE_MOVED]        = 0,
825b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_MOVE_COMBINING]     = 1,
835b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_MOVE_REDUCING]      = 1,
845b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_MOVE_EXPANDING]     = 1,
855b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_ACCEPTED]           = 1,
865b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_CONFLICT]           = 0,
875b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_PENDING]            = 0,
885b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_DENIED]             = 0,
895b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_RESIZED]            = 1,
905b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = 1,
915b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_CONFLICT] = 1,
925b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_PENDING]  = 1,
935b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_DENIED]   = 1,
945b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
955b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	};
965b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
975b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	return statuses[rsv->state];
985b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella}
995b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
1005b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella/*
1015b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella * Return the status bit for a reservations's companion DRP IE .
1025b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella */
1035b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panellaint uwb_rsv_companion_status(struct uwb_rsv *rsv)
1045b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella{
1055b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	static const int companion_statuses[] = {
1065b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_O_MOVE_EXPANDING]     = 0,
1075b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = 1,
1085b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_CONFLICT] = 0,
1095b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_PENDING]  = 0,
1105b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		[UWB_RSV_STATE_T_EXPANDING_DENIED]   = 0,
1115b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	};
1125b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
1135b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	return companion_statuses[rsv->state];
1145b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella}
1155b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
1168cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel/*
1178cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * Allocate a DRP IE.
1188cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel *
1198cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * To save having to free/allocate a DRP IE when its MAS changes,
1208cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * enough memory is allocated for the maxiumum number of DRP
1218cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * allocation fields.  This gives an overhead per reservation of up to
1228cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * (UWB_NUM_ZONES - 1) * 4 = 60 octets.
1238cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel */
1248cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabelstatic struct uwb_ie_drp *uwb_drp_ie_alloc(void)
1258cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel{
1268cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	struct uwb_ie_drp *drp_ie;
1278cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
1288cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	drp_ie = kzalloc(sizeof(struct uwb_ie_drp) +
1298cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			UWB_NUM_ZONES * sizeof(struct uwb_drp_alloc),
1308cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			GFP_KERNEL);
1318cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	if (drp_ie) {
1328cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		drp_ie->hdr.element_id = UWB_IE_DRP;
1338cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	}
1348cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	return drp_ie;
1358cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel}
1368cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
1378cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
1388cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel/*
1398cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * Fill a DRP IE's allocation fields from a MAS bitmap.
1408cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel */
1418cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabelstatic void uwb_drp_ie_from_bm(struct uwb_ie_drp *drp_ie,
1428cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			       struct uwb_mas_bm *mas)
1438cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel{
1448cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	int z, i, num_fields = 0, next = 0;
1458cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	struct uwb_drp_alloc *zones;
1468cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	__le16 current_bmp;
1478cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	DECLARE_BITMAP(tmp_bmp, UWB_NUM_MAS);
1488cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	DECLARE_BITMAP(tmp_mas_bm, UWB_MAS_PER_ZONE);
1498cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
1508cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	zones = drp_ie->allocs;
1518cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
1528cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	bitmap_copy(tmp_bmp, mas->bm, UWB_NUM_MAS);
1538cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
1548cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	/* Determine unique MAS bitmaps in zones from bitmap. */
1558cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	for (z = 0; z < UWB_NUM_ZONES; z++) {
1568cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		bitmap_copy(tmp_mas_bm, tmp_bmp, UWB_MAS_PER_ZONE);
1578cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		if (bitmap_weight(tmp_mas_bm, UWB_MAS_PER_ZONE) > 0) {
1588cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			bool found = false;
1598cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			current_bmp = (__le16) *tmp_mas_bm;
1608cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			for (i = 0; i < next; i++) {
1618cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel				if (current_bmp == zones[i].mas_bm) {
1628cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel					zones[i].zone_bm |= 1 << z;
1638cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel					found = true;
1648cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel					break;
1658cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel				}
1668cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			}
1678cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			if (!found)  {
1688cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel				num_fields++;
1698cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel				zones[next].zone_bm = 1 << z;
1708cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel				zones[next].mas_bm = current_bmp;
1718cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel				next++;
1728cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			}
1738cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		}
1748cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		bitmap_shift_right(tmp_bmp, tmp_bmp, UWB_MAS_PER_ZONE, UWB_NUM_MAS);
1758cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	}
1768cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
1778cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	/* Store in format ready for transmission (le16). */
1788cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	for (i = 0; i < num_fields; i++) {
1798cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		drp_ie->allocs[i].zone_bm = cpu_to_le16(zones[i].zone_bm);
1808cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		drp_ie->allocs[i].mas_bm = cpu_to_le16(zones[i].mas_bm);
1818cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	}
1828cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
1838cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	drp_ie->hdr.length = sizeof(struct uwb_ie_drp) - sizeof(struct uwb_ie_hdr)
1848cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		+ num_fields * sizeof(struct uwb_drp_alloc);
1858cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel}
1868cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
1878cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel/**
1888cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * uwb_drp_ie_update - update a reservation's DRP IE
1898cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * @rsv: the reservation
1908cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel */
1918cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabelint uwb_drp_ie_update(struct uwb_rsv *rsv)
1928cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel{
1938cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	struct uwb_ie_drp *drp_ie;
1945b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	struct uwb_rsv_move *mv;
1955b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	int unsafe;
1968cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
1975b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	if (rsv->state == UWB_RSV_STATE_NONE) {
1988cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		kfree(rsv->drp_ie);
1998cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		rsv->drp_ie = NULL;
2008cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		return 0;
2018cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	}
2025b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
2035b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	unsafe = rsv->mas.unsafe ? 1 : 0;
2048cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
2058cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	if (rsv->drp_ie == NULL) {
2068cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		rsv->drp_ie = uwb_drp_ie_alloc();
2078cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		if (rsv->drp_ie == NULL)
2088cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			return -ENOMEM;
2098cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	}
2108cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	drp_ie = rsv->drp_ie;
2118cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
2125b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	uwb_ie_drp_set_unsafe(drp_ie,       unsafe);
2135b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	uwb_ie_drp_set_tiebreaker(drp_ie,   rsv->tiebreaker);
2148cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	uwb_ie_drp_set_owner(drp_ie,        uwb_rsv_is_owner(rsv));
2155b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	uwb_ie_drp_set_status(drp_ie,       uwb_rsv_status(rsv));
2165b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	uwb_ie_drp_set_reason_code(drp_ie,  uwb_rsv_reason_code(rsv));
2178cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	uwb_ie_drp_set_stream_index(drp_ie, rsv->stream);
2188cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	uwb_ie_drp_set_type(drp_ie,         rsv->type);
2198cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
2208cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	if (uwb_rsv_is_owner(rsv)) {
2218cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		switch (rsv->target.type) {
2228cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		case UWB_RSV_TARGET_DEV:
2238cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			drp_ie->dev_addr = rsv->target.dev->dev_addr;
2248cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			break;
2258cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		case UWB_RSV_TARGET_DEVADDR:
2268cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			drp_ie->dev_addr = rsv->target.devaddr;
2278cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			break;
2288cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		}
2298cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	} else
2308cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		drp_ie->dev_addr = rsv->owner->dev_addr;
2318cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
2328cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	uwb_drp_ie_from_bm(drp_ie, &rsv->mas);
2338cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
2345b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	if (uwb_rsv_has_two_drp_ies(rsv)) {
2355b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		mv = &rsv->mv;
2365b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		if (mv->companion_drp_ie == NULL) {
2375b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella			mv->companion_drp_ie = uwb_drp_ie_alloc();
2385b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella			if (mv->companion_drp_ie == NULL)
2395b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella				return -ENOMEM;
2405b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		}
2415b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		drp_ie = mv->companion_drp_ie;
2425b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
2435b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		/* keep all the same configuration of the main drp_ie */
2445b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		memcpy(drp_ie, rsv->drp_ie, sizeof(struct uwb_ie_drp));
2455b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
2465b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
2475b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		/* FIXME: handle properly the unsafe bit */
2485b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		uwb_ie_drp_set_unsafe(drp_ie,       1);
2495b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		uwb_ie_drp_set_status(drp_ie,       uwb_rsv_companion_status(rsv));
2505b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		uwb_ie_drp_set_reason_code(drp_ie,  uwb_rsv_companion_reason_code(rsv));
2515b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
2525b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella		uwb_drp_ie_from_bm(drp_ie, &mv->companion_mas);
2535b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	}
2545b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
2558cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	rsv->ie_valid = true;
2568cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	return 0;
2578cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel}
2588cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
2598cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel/*
2608cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * Set MAS bits from given MAS bitmap in a single zone of large bitmap.
2618cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel *
2628cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * We are given a zone id and the MAS bitmap of bits that need to be set in
2638cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * this zone. Note that this zone may already have bits set and this only
2648cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * adds settings - we cannot simply assign the MAS bitmap contents to the
2658cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * zone contents. We iterate over the the bits (MAS) in the zone and set the
2668cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * bits that are set in the given MAS bitmap.
2678cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel */
2688cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabelstatic
2698cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabelvoid uwb_drp_ie_single_zone_to_bm(struct uwb_mas_bm *bm, u8 zone, u16 mas_bm)
2708cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel{
2718cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	int mas;
2728cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	u16 mas_mask;
2738cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
2748cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	for (mas = 0; mas < UWB_MAS_PER_ZONE; mas++) {
2758cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		mas_mask = 1 << mas;
2768cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		if (mas_bm & mas_mask)
2778cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			set_bit(zone * UWB_NUM_ZONES + mas, bm->bm);
2788cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	}
2798cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel}
2808cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
2818cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel/**
2828cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * uwb_drp_ie_zones_to_bm - convert DRP allocation fields to a bitmap
2838cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * @mas:    MAS bitmap that will be populated to correspond to the
2848cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel *          allocation fields in the DRP IE
2858cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * @drp_ie: the DRP IE that contains the allocation fields.
2868cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel *
2878cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * The input format is an array of MAS allocation fields (16 bit Zone
2888cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * bitmap, 16 bit MAS bitmap) as described in [ECMA-368] section
2898cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * 16.8.6. The output is a full 256 bit MAS bitmap.
2908cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel *
2918cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * We go over all the allocation fields, for each allocation field we
2928cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * know which zones are impacted. We iterate over all the zones
2938cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * impacted and call a function that will set the correct MAS bits in
2948cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel * each zone.
2958cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel */
2968cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabelvoid uwb_drp_ie_to_bm(struct uwb_mas_bm *bm, const struct uwb_ie_drp *drp_ie)
2978cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel{
2988cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	int numallocs = (drp_ie->hdr.length - 4) / 4;
2998cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	const struct uwb_drp_alloc *alloc;
3008cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	int cnt;
3018cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	u16 zone_bm, mas_bm;
3028cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	u8 zone;
3038cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	u16 zone_mask;
3048cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel
3055b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella	bitmap_zero(bm->bm, UWB_NUM_MAS);
3065b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
3078cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	for (cnt = 0; cnt < numallocs; cnt++) {
3088cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		alloc = &drp_ie->allocs[cnt];
3098cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		zone_bm = le16_to_cpu(alloc->zone_bm);
3108cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		mas_bm = le16_to_cpu(alloc->mas_bm);
3118cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		for (zone = 0; zone < UWB_NUM_ZONES; zone++)   {
3128cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			zone_mask = 1 << zone;
3138cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel			if (zone_bm & zone_mask)
3148cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel				uwb_drp_ie_single_zone_to_bm(bm, zone, mas_bm);
3158cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel		}
3168cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel	}
3178cc13a09474bb30d15dbf449767bb6d0198a8bf8David Vrabel}
3185b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella
319