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