Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.4 356 lines 9.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Ultra Wide Band 4 * Neighborhood Management Daemon 5 * 6 * Copyright (C) 2005-2006 Intel Corporation 7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 8 * 9 * This daemon takes care of maintaing information that describes the 10 * UWB neighborhood that the radios in this machine can see. It also 11 * keeps a tab of which devices are visible, makes sure each HC sits 12 * on a different channel to avoid interfering, etc. 13 * 14 * Different drivers (radio controller, device, any API in general) 15 * communicate with this daemon through an event queue. Daemon wakes 16 * up, takes a list of events and handles them one by one; handling 17 * function is extracted from a table based on the event's type and 18 * subtype. Events are freed only if the handling function says so. 19 * 20 * . Lock protecting the event list has to be an spinlock and locked 21 * with IRQSAVE because it might be called from an interrupt 22 * context (ie: when events arrive and the notification drops 23 * down from the ISR). 24 * 25 * . UWB radio controller drivers queue events to the daemon using 26 * uwbd_event_queue(). They just get the event, chew it to make it 27 * look like UWBD likes it and pass it in a buffer allocated with 28 * uwb_event_alloc(). 29 * 30 * EVENTS 31 * 32 * Events have a type, a subtype, a length, some other stuff and the 33 * data blob, which depends on the event. The header is 'struct 34 * uwb_event'; for payloads, see 'struct uwbd_evt_*'. 35 * 36 * EVENT HANDLER TABLES 37 * 38 * To find a handling function for an event, the type is used to index 39 * a subtype-table in the type-table. The subtype-table is indexed 40 * with the subtype to get the function that handles the event. Start 41 * with the main type-table 'uwbd_evt_type_handler'. 42 * 43 * DEVICES 44 * 45 * Devices are created when a bunch of beacons have been received and 46 * it is stablished that the device has stable radio presence. CREATED 47 * only, not configured. Devices are ONLY configured when an 48 * Application-Specific IE Probe is receieved, in which the device 49 * declares which Protocol ID it groks. Then the device is CONFIGURED 50 * (and the driver->probe() stuff of the device model is invoked). 51 * 52 * Devices are considered disconnected when a certain number of 53 * beacons are not received in an amount of time. 54 * 55 * Handler functions are called normally uwbd_evt_handle_*(). 56 */ 57#include <linux/kthread.h> 58#include <linux/slab.h> 59#include <linux/module.h> 60#include <linux/freezer.h> 61 62#include "uwb-internal.h" 63 64/* 65 * UWBD Event handler function signature 66 * 67 * Return !0 if the event needs not to be freed (ie the handler 68 * takes/took care of it). 0 means the daemon code will free the 69 * event. 70 * 71 * @evt->rc is already referenced and guaranteed to exist. See 72 * uwb_evt_handle(). 73 */ 74typedef int (*uwbd_evt_handler_f)(struct uwb_event *); 75 76/** 77 * Properties of a UWBD event 78 * 79 * @handler: the function that will handle this event 80 * @name: text name of event 81 */ 82struct uwbd_event { 83 uwbd_evt_handler_f handler; 84 const char *name; 85}; 86 87/* Table of handlers for and properties of the UWBD Radio Control Events */ 88static struct uwbd_event uwbd_urc_events[] = { 89 [UWB_RC_EVT_IE_RCV] = { 90 .handler = uwbd_evt_handle_rc_ie_rcv, 91 .name = "IE_RECEIVED" 92 }, 93 [UWB_RC_EVT_BEACON] = { 94 .handler = uwbd_evt_handle_rc_beacon, 95 .name = "BEACON_RECEIVED" 96 }, 97 [UWB_RC_EVT_BEACON_SIZE] = { 98 .handler = uwbd_evt_handle_rc_beacon_size, 99 .name = "BEACON_SIZE_CHANGE" 100 }, 101 [UWB_RC_EVT_BPOIE_CHANGE] = { 102 .handler = uwbd_evt_handle_rc_bpoie_change, 103 .name = "BPOIE_CHANGE" 104 }, 105 [UWB_RC_EVT_BP_SLOT_CHANGE] = { 106 .handler = uwbd_evt_handle_rc_bp_slot_change, 107 .name = "BP_SLOT_CHANGE" 108 }, 109 [UWB_RC_EVT_DRP_AVAIL] = { 110 .handler = uwbd_evt_handle_rc_drp_avail, 111 .name = "DRP_AVAILABILITY_CHANGE" 112 }, 113 [UWB_RC_EVT_DRP] = { 114 .handler = uwbd_evt_handle_rc_drp, 115 .name = "DRP" 116 }, 117 [UWB_RC_EVT_DEV_ADDR_CONFLICT] = { 118 .handler = uwbd_evt_handle_rc_dev_addr_conflict, 119 .name = "DEV_ADDR_CONFLICT", 120 }, 121}; 122 123 124 125struct uwbd_evt_type_handler { 126 const char *name; 127 struct uwbd_event *uwbd_events; 128 size_t size; 129}; 130 131/* Table of handlers for each UWBD Event type. */ 132static struct uwbd_evt_type_handler uwbd_urc_evt_type_handlers[] = { 133 [UWB_RC_CET_GENERAL] = { 134 .name = "URC", 135 .uwbd_events = uwbd_urc_events, 136 .size = ARRAY_SIZE(uwbd_urc_events), 137 }, 138}; 139 140static const struct uwbd_event uwbd_message_handlers[] = { 141 [UWB_EVT_MSG_RESET] = { 142 .handler = uwbd_msg_handle_reset, 143 .name = "reset", 144 }, 145}; 146 147/* 148 * Handle an URC event passed to the UWB Daemon 149 * 150 * @evt: the event to handle 151 * @returns: 0 if the event can be kfreed, !0 on the contrary 152 * (somebody else took ownership) [coincidentally, returning 153 * a <0 errno code will free it :)]. 154 * 155 * Looks up the two indirection tables (one for the type, one for the 156 * subtype) to decide which function handles it and then calls the 157 * handler. 158 * 159 * The event structure passed to the event handler has the radio 160 * controller in @evt->rc referenced. The reference will be dropped 161 * once the handler returns, so if it needs it for longer (async), 162 * it'll need to take another one. 163 */ 164static 165int uwbd_event_handle_urc(struct uwb_event *evt) 166{ 167 int result = -EINVAL; 168 struct uwbd_evt_type_handler *type_table; 169 uwbd_evt_handler_f handler; 170 u8 type, context; 171 u16 event; 172 173 type = evt->notif.rceb->bEventType; 174 event = le16_to_cpu(evt->notif.rceb->wEvent); 175 context = evt->notif.rceb->bEventContext; 176 177 if (type >= ARRAY_SIZE(uwbd_urc_evt_type_handlers)) 178 goto out; 179 type_table = &uwbd_urc_evt_type_handlers[type]; 180 if (type_table->uwbd_events == NULL) 181 goto out; 182 if (event >= type_table->size) 183 goto out; 184 handler = type_table->uwbd_events[event].handler; 185 if (handler == NULL) 186 goto out; 187 188 result = (*handler)(evt); 189out: 190 if (result < 0) 191 dev_err(&evt->rc->uwb_dev.dev, 192 "UWBD: event 0x%02x/%04x/%02x, handling failed: %d\n", 193 type, event, context, result); 194 return result; 195} 196 197static void uwbd_event_handle_message(struct uwb_event *evt) 198{ 199 struct uwb_rc *rc; 200 int result; 201 202 rc = evt->rc; 203 204 if (evt->message < 0 || evt->message >= ARRAY_SIZE(uwbd_message_handlers)) { 205 dev_err(&rc->uwb_dev.dev, "UWBD: invalid message type %d\n", evt->message); 206 return; 207 } 208 209 result = uwbd_message_handlers[evt->message].handler(evt); 210 if (result < 0) 211 dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n", 212 uwbd_message_handlers[evt->message].name, result); 213} 214 215static void uwbd_event_handle(struct uwb_event *evt) 216{ 217 struct uwb_rc *rc; 218 int should_keep; 219 220 rc = evt->rc; 221 222 if (rc->ready) { 223 switch (evt->type) { 224 case UWB_EVT_TYPE_NOTIF: 225 should_keep = uwbd_event_handle_urc(evt); 226 if (should_keep <= 0) 227 kfree(evt->notif.rceb); 228 break; 229 case UWB_EVT_TYPE_MSG: 230 uwbd_event_handle_message(evt); 231 break; 232 default: 233 dev_err(&rc->uwb_dev.dev, "UWBD: invalid event type %d\n", evt->type); 234 break; 235 } 236 } 237 238 __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */ 239} 240 241/** 242 * UWB Daemon 243 * 244 * Listens to all UWB notifications and takes care to track the state 245 * of the UWB neighbourhood for the kernel. When we do a run, we 246 * spinlock, move the list to a private copy and release the 247 * lock. Hold it as little as possible. Not a conflict: it is 248 * guaranteed we own the events in the private list. 249 * 250 * FIXME: should change so we don't have a 1HZ timer all the time, but 251 * only if there are devices. 252 */ 253static int uwbd(void *param) 254{ 255 struct uwb_rc *rc = param; 256 unsigned long flags; 257 struct uwb_event *evt; 258 int should_stop = 0; 259 260 while (1) { 261 wait_event_interruptible_timeout( 262 rc->uwbd.wq, 263 !list_empty(&rc->uwbd.event_list) 264 || (should_stop = kthread_should_stop()), 265 HZ); 266 if (should_stop) 267 break; 268 269 spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); 270 if (!list_empty(&rc->uwbd.event_list)) { 271 evt = list_first_entry(&rc->uwbd.event_list, struct uwb_event, list_node); 272 list_del(&evt->list_node); 273 } else 274 evt = NULL; 275 spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); 276 277 if (evt) { 278 uwbd_event_handle(evt); 279 kfree(evt); 280 } 281 282 uwb_beca_purge(rc); /* Purge devices that left */ 283 } 284 return 0; 285} 286 287 288/** Start the UWB daemon */ 289void uwbd_start(struct uwb_rc *rc) 290{ 291 struct task_struct *task = kthread_run(uwbd, rc, "uwbd"); 292 if (IS_ERR(task)) { 293 rc->uwbd.task = NULL; 294 printk(KERN_ERR "UWB: Cannot start management daemon; " 295 "UWB won't work\n"); 296 } else { 297 rc->uwbd.task = task; 298 rc->uwbd.pid = rc->uwbd.task->pid; 299 } 300} 301 302/* Stop the UWB daemon and free any unprocessed events */ 303void uwbd_stop(struct uwb_rc *rc) 304{ 305 if (rc->uwbd.task) 306 kthread_stop(rc->uwbd.task); 307 uwbd_flush(rc); 308} 309 310/* 311 * Queue an event for the management daemon 312 * 313 * When some lower layer receives an event, it uses this function to 314 * push it forward to the UWB daemon. 315 * 316 * Once you pass the event, you don't own it any more, but the daemon 317 * does. It will uwb_event_free() it when done, so make sure you 318 * uwb_event_alloc()ed it or bad things will happen. 319 * 320 * If the daemon is not running, we just free the event. 321 */ 322void uwbd_event_queue(struct uwb_event *evt) 323{ 324 struct uwb_rc *rc = evt->rc; 325 unsigned long flags; 326 327 spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); 328 if (rc->uwbd.pid != 0) { 329 list_add(&evt->list_node, &rc->uwbd.event_list); 330 wake_up_all(&rc->uwbd.wq); 331 } else { 332 __uwb_rc_put(evt->rc); 333 if (evt->type == UWB_EVT_TYPE_NOTIF) 334 kfree(evt->notif.rceb); 335 kfree(evt); 336 } 337 spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); 338 return; 339} 340 341void uwbd_flush(struct uwb_rc *rc) 342{ 343 struct uwb_event *evt, *nxt; 344 345 spin_lock_irq(&rc->uwbd.event_list_lock); 346 list_for_each_entry_safe(evt, nxt, &rc->uwbd.event_list, list_node) { 347 if (evt->rc == rc) { 348 __uwb_rc_put(rc); 349 list_del(&evt->list_node); 350 if (evt->type == UWB_EVT_TYPE_NOTIF) 351 kfree(evt->notif.rceb); 352 kfree(evt); 353 } 354 } 355 spin_unlock_irq(&rc->uwbd.event_list_lock); 356}