1183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/* 2183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Ultra Wide Band 3183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Life cycle of devices 4183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 5183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Copyright (C) 2005-2006 Intel Corporation 6183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 7183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 8183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * This program is free software; you can redistribute it and/or 9183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * modify it under the terms of the GNU General Public License version 10183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 2 as published by the Free Software Foundation. 11183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 12183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * This program is distributed in the hope that it will be useful, 13183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * but WITHOUT ANY WARRANTY; without even the implied warranty of 14183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * GNU General Public License for more details. 16183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 17183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * You should have received a copy of the GNU General Public License 18183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * along with this program; if not, write to the Free Software 19183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 02110-1301, USA. 21183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 22183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 23183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * FIXME: docs 24183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 25183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez#include <linux/kernel.h> 265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 27183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez#include <linux/device.h> 28475c0a6b2cff037ca522d3aff839024ab30ed7ebPaul Gortmaker#include <linux/export.h> 29183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez#include <linux/err.h> 30183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez#include <linux/kdev_t.h> 31183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez#include <linux/random.h> 320b992080a98fa6f0722c43060819f7c311203a1cPaul Gortmaker#include <linux/stat.h> 33183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez#include "uwb-internal.h" 34183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 35183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/* We initialize addresses to 0xff (invalid, as it is bcast) */ 36183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic inline void uwb_dev_addr_init(struct uwb_dev_addr *addr) 37183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 38183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez memset(&addr->data, 0xff, sizeof(addr->data)); 39183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 40183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 41183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic inline void uwb_mac_addr_init(struct uwb_mac_addr *addr) 42183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 43183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez memset(&addr->data, 0xff, sizeof(addr->data)); 44183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 45183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 46183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/* @returns !0 if a device @addr is a broadcast address */ 47183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic inline int uwb_dev_addr_bcast(const struct uwb_dev_addr *addr) 48183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 49183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez static const struct uwb_dev_addr bcast = { .data = { 0xff, 0xff } }; 50183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return !uwb_dev_addr_cmp(addr, &bcast); 51183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 52183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 53183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/* 54183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Add callback @new to be called when an event occurs in @rc. 55183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 56183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezint uwb_notifs_register(struct uwb_rc *rc, struct uwb_notifs_handler *new) 57183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 58183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (mutex_lock_interruptible(&rc->notifs_chain.mutex)) 59183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return -ERESTARTSYS; 60183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez list_add(&new->list_node, &rc->notifs_chain.list); 61183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_unlock(&rc->notifs_chain.mutex); 62183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return 0; 63183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 64183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_notifs_register); 65183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 66183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/* 67183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Remove event handler (callback) 68183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 69183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezint uwb_notifs_deregister(struct uwb_rc *rc, struct uwb_notifs_handler *entry) 70183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 71183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (mutex_lock_interruptible(&rc->notifs_chain.mutex)) 72183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return -ERESTARTSYS; 73183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez list_del(&entry->list_node); 74183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_unlock(&rc->notifs_chain.mutex); 75183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return 0; 76183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 77183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_notifs_deregister); 78183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 79183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/* 80183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Notify all event handlers of a given event on @rc 81183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 82183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * We are called with a valid reference to the device, or NULL if the 83183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * event is not for a particular event (e.g., a BG join event). 84183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 85183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezvoid uwb_notify(struct uwb_rc *rc, struct uwb_dev *uwb_dev, enum uwb_notifs event) 86183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 87183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_notifs_handler *handler; 88183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (mutex_lock_interruptible(&rc->notifs_chain.mutex)) 89183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return; 90183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (!list_empty(&rc->notifs_chain.list)) { 91183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez list_for_each_entry(handler, &rc->notifs_chain.list, list_node) { 92183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez handler->cb(handler->data, uwb_dev, event); 93183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez } 94183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez } 95183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_unlock(&rc->notifs_chain.mutex); 96183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 97183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 98183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/* 99183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Release the backing device of a uwb_dev that has been dynamically allocated. 100183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 101183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic void uwb_dev_sys_release(struct device *dev) 102183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 103183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 104183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 105183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_bce_put(uwb_dev->bce); 106183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez memset(uwb_dev, 0x69, sizeof(*uwb_dev)); 107183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez kfree(uwb_dev); 108183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 109183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 110183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/* 111183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Initialize a UWB device instance 112183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 113183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Alloc, zero and call this function. 114183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 115183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezvoid uwb_dev_init(struct uwb_dev *uwb_dev) 116183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 117183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_init(&uwb_dev->mutex); 118183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez device_initialize(&uwb_dev->dev); 119183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev->dev.release = uwb_dev_sys_release; 120183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev_addr_init(&uwb_dev->dev_addr); 121183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_mac_addr_init(&uwb_dev->mac_addr); 122183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez bitmap_fill(uwb_dev->streams, UWB_NUM_GLOBAL_STREAMS); 123183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 124183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 125183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic ssize_t uwb_dev_EUI_48_show(struct device *dev, 126183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device_attribute *attr, char *buf) 127183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 128183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 129183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez char addr[UWB_ADDR_STRSIZE]; 130183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 131183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_mac_addr_print(addr, sizeof(addr), &uwb_dev->mac_addr); 132183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return sprintf(buf, "%s\n", addr); 133183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 134183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic DEVICE_ATTR(EUI_48, S_IRUGO, uwb_dev_EUI_48_show, NULL); 135183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 136183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic ssize_t uwb_dev_DevAddr_show(struct device *dev, 137183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device_attribute *attr, char *buf) 138183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 139183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 140183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez char addr[UWB_ADDR_STRSIZE]; 141183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 142183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev_addr_print(addr, sizeof(addr), &uwb_dev->dev_addr); 143183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return sprintf(buf, "%s\n", addr); 144183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 145183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic DEVICE_ATTR(DevAddr, S_IRUGO, uwb_dev_DevAddr_show, NULL); 146183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 147183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/* 148183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Show the BPST of this device. 149183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 150183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Calculated from the receive time of the device's beacon and it's 151183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * slot number. 152183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 153183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic ssize_t uwb_dev_BPST_show(struct device *dev, 154183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device_attribute *attr, char *buf) 155183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 156183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 157183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_beca_e *bce; 158183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_beacon_frame *bf; 159183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez u16 bpst; 160183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 161183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez bce = uwb_dev->bce; 162183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_lock(&bce->mutex); 163183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez bf = (struct uwb_beacon_frame *)bce->be->BeaconInfo; 164183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez bpst = bce->be->wBPSTOffset 165183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez - (u16)(bf->Beacon_Slot_Number * UWB_BEACON_SLOT_LENGTH_US); 166183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_unlock(&bce->mutex); 167183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 168183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return sprintf(buf, "%d\n", bpst); 169183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 170183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic DEVICE_ATTR(BPST, S_IRUGO, uwb_dev_BPST_show, NULL); 171183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 172183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/* 173183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Show the IEs a device is beaconing 174183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 175183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * We need to access the beacon cache, so we just lock it really 176183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * quick, print the IEs and unlock. 177183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 178183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * We have a reference on the cache entry, so that should be 179183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * quite safe. 180183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 181183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic ssize_t uwb_dev_IEs_show(struct device *dev, 182183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device_attribute *attr, char *buf) 183183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 184183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 185183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 186183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return uwb_bce_print_IEs(uwb_dev, uwb_dev->bce, buf, PAGE_SIZE); 187183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 188183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic DEVICE_ATTR(IEs, S_IRUGO | S_IWUSR, uwb_dev_IEs_show, NULL); 189183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 190183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic ssize_t uwb_dev_LQE_show(struct device *dev, 191183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device_attribute *attr, char *buf) 192183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 193183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 194183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_beca_e *bce = uwb_dev->bce; 195183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez size_t result; 196183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 197183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_lock(&bce->mutex); 198183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez result = stats_show(&uwb_dev->bce->lqe_stats, buf); 199183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_unlock(&bce->mutex); 200183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return result; 201183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 202183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 203183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic ssize_t uwb_dev_LQE_store(struct device *dev, 204183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device_attribute *attr, 205183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez const char *buf, size_t size) 206183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 207183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 208183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_beca_e *bce = uwb_dev->bce; 209183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez ssize_t result; 210183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 211183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_lock(&bce->mutex); 212183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez result = stats_store(&uwb_dev->bce->lqe_stats, buf, size); 213183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_unlock(&bce->mutex); 214183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return result; 215183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 216183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic DEVICE_ATTR(LQE, S_IRUGO | S_IWUSR, uwb_dev_LQE_show, uwb_dev_LQE_store); 217183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 218183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic ssize_t uwb_dev_RSSI_show(struct device *dev, 219183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device_attribute *attr, char *buf) 220183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 221183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 222183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_beca_e *bce = uwb_dev->bce; 223183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez size_t result; 224183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 225183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_lock(&bce->mutex); 226183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez result = stats_show(&uwb_dev->bce->rssi_stats, buf); 227183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_unlock(&bce->mutex); 228183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return result; 229183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 230183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 231183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic ssize_t uwb_dev_RSSI_store(struct device *dev, 232183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device_attribute *attr, 233183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez const char *buf, size_t size) 234183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 235183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 236183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_beca_e *bce = uwb_dev->bce; 237183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez ssize_t result; 238183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 239183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_lock(&bce->mutex); 240183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez result = stats_store(&uwb_dev->bce->rssi_stats, buf, size); 241183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_unlock(&bce->mutex); 242183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return result; 243183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 244183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic DEVICE_ATTR(RSSI, S_IRUGO | S_IWUSR, uwb_dev_RSSI_show, uwb_dev_RSSI_store); 245183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 246183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 247183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic struct attribute *dev_attrs[] = { 248183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez &dev_attr_EUI_48.attr, 249183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez &dev_attr_DevAddr.attr, 250183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez &dev_attr_BPST.attr, 251183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez &dev_attr_IEs.attr, 252183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez &dev_attr_LQE.attr, 253183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez &dev_attr_RSSI.attr, 254183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez NULL, 255183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez}; 256183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 257183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic struct attribute_group dev_attr_group = { 258183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez .attrs = dev_attrs, 259183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez}; 260183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 261a4dbd6740df0872cdf0a86841f75beec8381964dDavid Brownellstatic const struct attribute_group *groups[] = { 262183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez &dev_attr_group, 263183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez NULL, 264183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez}; 265183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 266183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/** 267183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Device SYSFS registration 268183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 269183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 270183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 271183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic int __uwb_dev_sys_add(struct uwb_dev *uwb_dev, struct device *parent_dev) 272183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 273183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device *dev; 274183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 275183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev = &uwb_dev->dev; 276183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez /* Device sysfs files are only useful for neighbor devices not 277183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez local radio controllers. */ 278183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (&uwb_dev->rc->uwb_dev != uwb_dev) 279183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev->groups = groups; 280183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev->parent = parent_dev; 281183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev_set_drvdata(dev, uwb_dev); 282183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 283bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel return device_add(dev); 284183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 285183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 286183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 287183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic void __uwb_dev_sys_rm(struct uwb_dev *uwb_dev) 288183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 289183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev_set_drvdata(&uwb_dev->dev, NULL); 290183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez device_del(&uwb_dev->dev); 291183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 292183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 293183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 294183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/** 295183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Register and initialize a new UWB device 296183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 297183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Did you call uwb_dev_init() on it? 298183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 299183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * @parent_rc: is the parent radio controller who has the link to the 300183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * device. When registering the UWB device that is a UWB 301183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Radio Controller, we point back to it. 302183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 303183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * If registering the device that is part of a radio, caller has set 304183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * rc->uwb_dev->dev. Otherwise it is to be left NULL--a new one will 305183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * be allocated. 306183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 307183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezint uwb_dev_add(struct uwb_dev *uwb_dev, struct device *parent_dev, 308183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_rc *parent_rc) 309183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 310183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez int result; 311183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device *dev; 312183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 313183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez BUG_ON(uwb_dev == NULL); 314183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez BUG_ON(parent_dev == NULL); 315183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez BUG_ON(parent_rc == NULL); 316183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 317183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_lock(&uwb_dev->mutex); 318183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev = &uwb_dev->dev; 319183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev->rc = parent_rc; 320183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez result = __uwb_dev_sys_add(uwb_dev, parent_dev); 321183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (result < 0) 322183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez printk(KERN_ERR "UWB: unable to register dev %s with sysfs: %d\n", 323183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev_name(dev), result); 324183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_unlock(&uwb_dev->mutex); 325183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return result; 326183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 327183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 328183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 329183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezvoid uwb_dev_rm(struct uwb_dev *uwb_dev) 330183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 331183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_lock(&uwb_dev->mutex); 332183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez __uwb_dev_sys_rm(uwb_dev); 333183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez mutex_unlock(&uwb_dev->mutex); 334183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 335183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 336183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 337183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstatic 338183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezint __uwb_dev_try_get(struct device *dev, void *__target_uwb_dev) 339183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 340183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *target_uwb_dev = __target_uwb_dev; 341183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev = to_uwb_dev(dev); 342183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (uwb_dev == target_uwb_dev) { 343183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev_get(uwb_dev); 344183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return 1; 345183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez } else 346183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return 0; 347183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 348183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 349183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 350183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/** 351183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Given a UWB device descriptor, validate and refcount it 352183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 353183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * @returns NULL if the device does not exist or is quiescing; the ptr to 354183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * it otherwise. 355183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 356183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezstruct uwb_dev *uwb_dev_try_get(struct uwb_rc *rc, struct uwb_dev *uwb_dev) 357183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 358183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (uwb_dev_for_each(rc, __uwb_dev_try_get, uwb_dev)) 359183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return uwb_dev; 360183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez else 361183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return NULL; 362183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 363183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_dev_try_get); 364183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 365183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 366183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/** 367183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Remove a device from the system [grunt for other functions] 368183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 369183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezint __uwb_dev_offair(struct uwb_dev *uwb_dev, struct uwb_rc *rc) 370183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 371183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device *dev = &uwb_dev->dev; 372183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez char macbuf[UWB_ADDR_STRSIZE], devbuf[UWB_ADDR_STRSIZE]; 373183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 374183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_mac_addr_print(macbuf, sizeof(macbuf), &uwb_dev->mac_addr); 375183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev_addr_print(devbuf, sizeof(devbuf), &uwb_dev->dev_addr); 376183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev_info(dev, "uwb device (mac %s dev %s) disconnected from %s %s\n", 377183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez macbuf, devbuf, 378183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez rc ? rc->uwb_dev.dev.parent->bus->name : "n/a", 379183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez rc ? dev_name(rc->uwb_dev.dev.parent) : ""); 380183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev_rm(uwb_dev); 3813af373021fa32f8f787bfbdcc1a9277a287bde4eStefano Panella list_del(&uwb_dev->bce->node); 3823af373021fa32f8f787bfbdcc1a9277a287bde4eStefano Panella uwb_bce_put(uwb_dev->bce); 383183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev_put(uwb_dev); /* for the creation in _onair() */ 384bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel 385183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return 0; 386183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 387183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 388183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 389183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/** 390183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * A device went off the air, clean up after it! 391183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 392183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * This is called by the UWB Daemon (through the beacon purge function 393183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * uwb_bcn_cache_purge) when it is detected that a device has been in 394183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * radio silence for a while. 395183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 396183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * If this device is actually a local radio controller we don't need 397183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * to go through the offair process, as it is not registered as that. 398183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 399183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * NOTE: uwb_bcn_cache.mutex is held! 400183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 401183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezvoid uwbd_dev_offair(struct uwb_beca_e *bce) 402183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 403183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev; 404183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 405183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev = bce->uwb_dev; 406183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (uwb_dev) { 407183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_notify(uwb_dev->rc, uwb_dev, UWB_NOTIF_OFFAIR); 408183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez __uwb_dev_offair(uwb_dev, uwb_dev->rc); 409183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez } 410183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 411183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 412183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 413183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/** 414183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * A device went on the air, start it up! 415183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 416183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * This is called by the UWB Daemon when it is detected that a device 417183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * has popped up in the radio range of the radio controller. 418183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 419183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * It will just create the freaking device, register the beacon and 420183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * stuff and yatla, done. 421183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 422183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 423183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * NOTE: uwb_beca.mutex is held, bce->mutex is held 424183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 425183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezvoid uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce) 426183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 427183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez int result; 428183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct device *dev = &rc->uwb_dev.dev; 429183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez struct uwb_dev *uwb_dev; 430183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez char macbuf[UWB_ADDR_STRSIZE], devbuf[UWB_ADDR_STRSIZE]; 431183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 432183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_mac_addr_print(macbuf, sizeof(macbuf), bce->mac_addr); 433183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev_addr_print(devbuf, sizeof(devbuf), &bce->dev_addr); 43492c4d9bd1648b3eaca6b8b8f8932eec390ba7327David Vrabel uwb_dev = kzalloc(sizeof(struct uwb_dev), GFP_KERNEL); 435183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (uwb_dev == NULL) { 436183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev_err(dev, "new device %s: Cannot allocate memory\n", 437183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez macbuf); 438183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return; 439183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez } 440183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev_init(uwb_dev); /* This sets refcnt to one, we own it */ 441183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev->mac_addr = *bce->mac_addr; 442183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev->dev_addr = bce->dev_addr; 443183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev_set_name(&uwb_dev->dev, macbuf); 444183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez result = uwb_dev_add(uwb_dev, &rc->uwb_dev.dev, rc); 445183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez if (result < 0) { 446183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev_err(dev, "new device %s: cannot instantiate device\n", 447183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez macbuf); 448183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez goto error_dev_add; 449183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez } 450183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez /* plug the beacon cache */ 451183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez bce->uwb_dev = uwb_dev; 452183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_dev->bce = bce; 453183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_bce_get(bce); /* released in uwb_dev_sys_release() */ 454183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev_info(dev, "uwb device (mac %s dev %s) connected to %s %s\n", 455183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez macbuf, devbuf, rc->uwb_dev.dev.parent->bus->name, 456183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez dev_name(rc->uwb_dev.dev.parent)); 457183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez uwb_notify(rc, uwb_dev, UWB_NOTIF_ONAIR); 458183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return; 459183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 460183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezerror_dev_add: 461183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez kfree(uwb_dev); 462183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return; 463183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 464183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez 465183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez/** 466183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * Iterate over the list of UWB devices, calling a @function on each 467183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 468183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * See docs for bus_for_each().... 469183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * 470183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * @rc: radio controller for the devices. 471183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * @function: function to call. 472183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * @priv: data to pass to @function. 473183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * @returns: 0 if no invocation of function() returned a value 474183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez * different to zero. That value otherwise. 475183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez */ 476183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalezint uwb_dev_for_each(struct uwb_rc *rc, uwb_dev_for_each_f function, void *priv) 477183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez{ 478183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez return device_for_each_child(&rc->uwb_dev.dev, priv, function); 479183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-Gonzalez} 480183b9b592a622a7719ee38e275fd7ff3aaf74d0dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_dev_for_each); 481