1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 /* 3 * Surface System Aggregator Module (SSAM) bus and client-device subsystem. 4 * 5 * Main interface for the surface-aggregator bus, surface-aggregator client 6 * devices, and respective drivers building on top of the SSAM controller. 7 * Provides support for non-platform/non-ACPI SSAM clients via dedicated 8 * subsystem. 9 * 10 * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com> 11 */ 12 13 #ifndef _LINUX_SURFACE_AGGREGATOR_DEVICE_H 14 #define _LINUX_SURFACE_AGGREGATOR_DEVICE_H 15 16 #include <linux/device.h> 17 #include <linux/mod_devicetable.h> 18 #include <linux/property.h> 19 #include <linux/types.h> 20 21 #include <linux/surface_aggregator/controller.h> 22 23 24 /* -- Surface System Aggregator Module bus. --------------------------------- */ 25 26 /** 27 * enum ssam_device_domain - SAM device domain. 28 * @SSAM_DOMAIN_VIRTUAL: Virtual device. 29 * @SSAM_DOMAIN_SERIALHUB: Physical device connected via Surface Serial Hub. 30 */ 31 enum ssam_device_domain { 32 SSAM_DOMAIN_VIRTUAL = 0x00, 33 SSAM_DOMAIN_SERIALHUB = 0x01, 34 }; 35 36 /** 37 * enum ssam_virtual_tc - Target categories for the virtual SAM domain. 38 * @SSAM_VIRTUAL_TC_HUB: Device hub category. 39 */ 40 enum ssam_virtual_tc { 41 SSAM_VIRTUAL_TC_HUB = 0x00, 42 }; 43 44 /** 45 * struct ssam_device_uid - Unique identifier for SSAM device. 46 * @domain: Domain of the device. 47 * @category: Target category of the device. 48 * @target: Target ID of the device. 49 * @instance: Instance ID of the device. 50 * @function: Sub-function of the device. This field can be used to split a 51 * single SAM device into multiple virtual subdevices to separate 52 * different functionality of that device and allow one driver per 53 * such functionality. 54 */ 55 struct ssam_device_uid { 56 u8 domain; 57 u8 category; 58 u8 target; 59 u8 instance; 60 u8 function; 61 }; 62 63 /* 64 * Special values for device matching. 65 * 66 * These values are intended to be used with SSAM_DEVICE(), SSAM_VDEV(), and 67 * SSAM_SDEV() exclusively. Specifically, they are used to initialize the 68 * match_flags member of the device ID structure. Do not use them directly 69 * with struct ssam_device_id or struct ssam_device_uid. 70 */ 71 #define SSAM_SSH_TID_ANY 0xffff 72 #define SSAM_SSH_IID_ANY 0xffff 73 #define SSAM_SSH_FUN_ANY 0xffff 74 75 /** 76 * SSAM_DEVICE() - Initialize a &struct ssam_device_id with the given 77 * parameters. 78 * @d: Domain of the device. 79 * @cat: Target category of the device. 80 * @tid: Target ID of the device. 81 * @iid: Instance ID of the device. 82 * @fun: Sub-function of the device. 83 * 84 * Initializes a &struct ssam_device_id with the given parameters. See &struct 85 * ssam_device_uid for details regarding the parameters. The special values 86 * %SSAM_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and %SSAM_SSH_FUN_ANY can be used to specify that 87 * matching should ignore target ID, instance ID, and/or sub-function, 88 * respectively. This macro initializes the ``match_flags`` field based on the 89 * given parameters. 90 * 91 * Note: The parameters @d and @cat must be valid &u8 values, the parameters 92 * @tid, @iid, and @fun must be either valid &u8 values or %SSAM_SSH_TID_ANY, 93 * %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values are not 94 * allowed. 95 */ 96 #define SSAM_DEVICE(d, cat, tid, iid, fun) \ 97 .match_flags = (((tid) != SSAM_SSH_TID_ANY) ? SSAM_MATCH_TARGET : 0) \ 98 | (((iid) != SSAM_SSH_IID_ANY) ? SSAM_MATCH_INSTANCE : 0) \ 99 | (((fun) != SSAM_SSH_FUN_ANY) ? SSAM_MATCH_FUNCTION : 0), \ 100 .domain = d, \ 101 .category = cat, \ 102 .target = __builtin_choose_expr((tid) != SSAM_SSH_TID_ANY, (tid), 0), \ 103 .instance = __builtin_choose_expr((iid) != SSAM_SSH_IID_ANY, (iid), 0), \ 104 .function = __builtin_choose_expr((fun) != SSAM_SSH_FUN_ANY, (fun), 0) 105 106 /** 107 * SSAM_VDEV() - Initialize a &struct ssam_device_id as virtual device with 108 * the given parameters. 109 * @cat: Target category of the device. 110 * @tid: Target ID of the device. 111 * @iid: Instance ID of the device. 112 * @fun: Sub-function of the device. 113 * 114 * Initializes a &struct ssam_device_id with the given parameters in the 115 * virtual domain. See &struct ssam_device_uid for details regarding the 116 * parameters. The special values %SSAM_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and 117 * %SSAM_SSH_FUN_ANY can be used to specify that matching should ignore target ID, 118 * instance ID, and/or sub-function, respectively. This macro initializes the 119 * ``match_flags`` field based on the given parameters. 120 * 121 * Note: The parameter @cat must be a valid &u8 value, the parameters @tid, 122 * @iid, and @fun must be either valid &u8 values or %SSAM_SSH_TID_ANY, 123 * %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values are not 124 * allowed. 125 */ 126 #define SSAM_VDEV(cat, tid, iid, fun) \ 127 SSAM_DEVICE(SSAM_DOMAIN_VIRTUAL, SSAM_VIRTUAL_TC_##cat, SSAM_SSH_TID_##tid, iid, fun) 128 129 /** 130 * SSAM_SDEV() - Initialize a &struct ssam_device_id as physical SSH device 131 * with the given parameters. 132 * @cat: Target category of the device. 133 * @tid: Target ID of the device. 134 * @iid: Instance ID of the device. 135 * @fun: Sub-function of the device. 136 * 137 * Initializes a &struct ssam_device_id with the given parameters in the SSH 138 * domain. See &struct ssam_device_uid for details regarding the parameters. 139 * The special values %SSAM_SSH_TID_ANY, %SSAM_SSH_IID_ANY, and 140 * %SSAM_SSH_FUN_ANY can be used to specify that matching should ignore target 141 * ID, instance ID, and/or sub-function, respectively. This macro initializes 142 * the ``match_flags`` field based on the given parameters. 143 * 144 * Note: The parameter @cat must be a valid &u8 value, the parameters @tid, 145 * @iid, and @fun must be either valid &u8 values or %SSAM_SSH_TID_ANY, 146 * %SSAM_SSH_IID_ANY, or %SSAM_SSH_FUN_ANY, respectively. Other non-&u8 values 147 * are not allowed. 148 */ 149 #define SSAM_SDEV(cat, tid, iid, fun) \ 150 SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, SSAM_SSH_TID_##tid, iid, fun) 151 152 /* 153 * enum ssam_device_flags - Flags for SSAM client devices. 154 * @SSAM_DEVICE_HOT_REMOVED_BIT: 155 * The device has been hot-removed. Further communication with it may time 156 * out and should be avoided. 157 */ 158 enum ssam_device_flags { 159 SSAM_DEVICE_HOT_REMOVED_BIT = 0, 160 }; 161 162 /** 163 * struct ssam_device - SSAM client device. 164 * @dev: Driver model representation of the device. 165 * @ctrl: SSAM controller managing this device. 166 * @uid: UID identifying the device. 167 * @flags: Device state flags, see &enum ssam_device_flags. 168 */ 169 struct ssam_device { 170 struct device dev; 171 struct ssam_controller *ctrl; 172 173 struct ssam_device_uid uid; 174 175 unsigned long flags; 176 }; 177 178 /** 179 * struct ssam_device_driver - SSAM client device driver. 180 * @driver: Base driver model structure. 181 * @match_table: Match table specifying which devices the driver should bind to. 182 * @probe: Called when the driver is being bound to a device. 183 * @remove: Called when the driver is being unbound from the device. 184 */ 185 struct ssam_device_driver { 186 struct device_driver driver; 187 188 const struct ssam_device_id *match_table; 189 190 int (*probe)(struct ssam_device *sdev); 191 void (*remove)(struct ssam_device *sdev); 192 }; 193 194 #ifdef CONFIG_SURFACE_AGGREGATOR_BUS 195 196 extern const struct device_type ssam_device_type; 197 198 /** 199 * is_ssam_device() - Check if the given device is a SSAM client device. 200 * @d: The device to test the type of. 201 * 202 * Return: Returns %true if the specified device is of type &struct 203 * ssam_device, i.e. the device type points to %ssam_device_type, and %false 204 * otherwise. 205 */ 206 static inline bool is_ssam_device(struct device *d) 207 { 208 return d->type == &ssam_device_type; 209 } 210 211 #else /* CONFIG_SURFACE_AGGREGATOR_BUS */ 212 213 static inline bool is_ssam_device(struct device *d) 214 { 215 return false; 216 } 217 218 #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */ 219 220 /** 221 * to_ssam_device() - Casts the given device to a SSAM client device. 222 * @d: The device to cast. 223 * 224 * Casts the given &struct device to a &struct ssam_device. The caller has to 225 * ensure that the given device is actually enclosed in a &struct ssam_device, 226 * e.g. by calling is_ssam_device(). 227 * 228 * Return: Returns a pointer to the &struct ssam_device wrapping the given 229 * device @d. 230 */ 231 #define to_ssam_device(d) container_of_const(d, struct ssam_device, dev) 232 233 /** 234 * to_ssam_device_driver() - Casts the given device driver to a SSAM client 235 * device driver. 236 * @d: The driver to cast. 237 * 238 * Casts the given &struct device_driver to a &struct ssam_device_driver. The 239 * caller has to ensure that the given driver is actually enclosed in a 240 * &struct ssam_device_driver. 241 * 242 * Return: Returns the pointer to the &struct ssam_device_driver wrapping the 243 * given device driver @d. 244 */ 245 #define to_ssam_device_driver(d) container_of_const(d, struct ssam_device_driver, driver) 246 247 const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table, 248 const struct ssam_device_uid uid); 249 250 const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev); 251 252 const void *ssam_device_get_match_data(const struct ssam_device *dev); 253 254 struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl, 255 struct ssam_device_uid uid); 256 257 int ssam_device_add(struct ssam_device *sdev); 258 void ssam_device_remove(struct ssam_device *sdev); 259 260 /** 261 * ssam_device_mark_hot_removed() - Mark the given device as hot-removed. 262 * @sdev: The device to mark as hot-removed. 263 * 264 * Mark the device as having been hot-removed. This signals drivers using the 265 * device that communication with the device should be avoided and may lead to 266 * timeouts. 267 */ 268 static inline void ssam_device_mark_hot_removed(struct ssam_device *sdev) 269 { 270 dev_dbg(&sdev->dev, "marking device as hot-removed\n"); 271 set_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags); 272 } 273 274 /** 275 * ssam_device_is_hot_removed() - Check if the given device has been 276 * hot-removed. 277 * @sdev: The device to check. 278 * 279 * Checks if the given device has been marked as hot-removed. See 280 * ssam_device_mark_hot_removed() for more details. 281 * 282 * Return: Returns ``true`` if the device has been marked as hot-removed. 283 */ 284 static inline bool ssam_device_is_hot_removed(struct ssam_device *sdev) 285 { 286 return test_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags); 287 } 288 289 /** 290 * ssam_device_get() - Increment reference count of SSAM client device. 291 * @sdev: The device to increment the reference count of. 292 * 293 * Increments the reference count of the given SSAM client device by 294 * incrementing the reference count of the enclosed &struct device via 295 * get_device(). 296 * 297 * See ssam_device_put() for the counter-part of this function. 298 * 299 * Return: Returns the device provided as input. 300 */ 301 static inline struct ssam_device *ssam_device_get(struct ssam_device *sdev) 302 { 303 return sdev ? to_ssam_device(get_device(&sdev->dev)) : NULL; 304 } 305 306 /** 307 * ssam_device_put() - Decrement reference count of SSAM client device. 308 * @sdev: The device to decrement the reference count of. 309 * 310 * Decrements the reference count of the given SSAM client device by 311 * decrementing the reference count of the enclosed &struct device via 312 * put_device(). 313 * 314 * See ssam_device_get() for the counter-part of this function. 315 */ 316 static inline void ssam_device_put(struct ssam_device *sdev) 317 { 318 if (sdev) 319 put_device(&sdev->dev); 320 } 321 322 /** 323 * ssam_device_get_drvdata() - Get driver-data of SSAM client device. 324 * @sdev: The device to get the driver-data from. 325 * 326 * Return: Returns the driver-data of the given device, previously set via 327 * ssam_device_set_drvdata(). 328 */ 329 static inline void *ssam_device_get_drvdata(struct ssam_device *sdev) 330 { 331 return dev_get_drvdata(&sdev->dev); 332 } 333 334 /** 335 * ssam_device_set_drvdata() - Set driver-data of SSAM client device. 336 * @sdev: The device to set the driver-data of. 337 * @data: The data to set the device's driver-data pointer to. 338 */ 339 static inline void ssam_device_set_drvdata(struct ssam_device *sdev, void *data) 340 { 341 dev_set_drvdata(&sdev->dev, data); 342 } 343 344 int __ssam_device_driver_register(struct ssam_device_driver *d, struct module *o); 345 void ssam_device_driver_unregister(struct ssam_device_driver *d); 346 347 /** 348 * ssam_device_driver_register() - Register a SSAM client device driver. 349 * @drv: The driver to register. 350 */ 351 #define ssam_device_driver_register(drv) \ 352 __ssam_device_driver_register(drv, THIS_MODULE) 353 354 /** 355 * module_ssam_device_driver() - Helper macro for SSAM device driver 356 * registration. 357 * @drv: The driver managed by this module. 358 * 359 * Helper macro to register a SSAM device driver via module_init() and 360 * module_exit(). This macro may only be used once per module and replaces the 361 * aforementioned definitions. 362 */ 363 #define module_ssam_device_driver(drv) \ 364 module_driver(drv, ssam_device_driver_register, \ 365 ssam_device_driver_unregister) 366 367 368 /* -- Helpers for controller and hub devices. ------------------------------- */ 369 370 #ifdef CONFIG_SURFACE_AGGREGATOR_BUS 371 372 int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl, 373 struct fwnode_handle *node); 374 void ssam_remove_clients(struct device *dev); 375 376 #else /* CONFIG_SURFACE_AGGREGATOR_BUS */ 377 378 static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl, 379 struct fwnode_handle *node) 380 { 381 return 0; 382 } 383 384 static inline void ssam_remove_clients(struct device *dev) {} 385 386 #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */ 387 388 /** 389 * ssam_register_clients() - Register all client devices defined under the 390 * given parent device. 391 * @dev: The parent device under which clients should be registered. 392 * @ctrl: The controller with which client should be registered. 393 * 394 * Register all clients that have via firmware nodes been defined as children 395 * of the given (parent) device. The respective child firmware nodes will be 396 * associated with the correspondingly created child devices. 397 * 398 * The given controller will be used to instantiate the new devices. See 399 * ssam_device_add() for details. 400 * 401 * Return: Returns zero on success, nonzero on failure. 402 */ 403 static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl) 404 { 405 return __ssam_register_clients(dev, ctrl, dev_fwnode(dev)); 406 } 407 408 /** 409 * ssam_device_register_clients() - Register all client devices defined under 410 * the given SSAM parent device. 411 * @sdev: The parent device under which clients should be registered. 412 * 413 * Register all clients that have via firmware nodes been defined as children 414 * of the given (parent) device. The respective child firmware nodes will be 415 * associated with the correspondingly created child devices. 416 * 417 * The controller used by the parent device will be used to instantiate the new 418 * devices. See ssam_device_add() for details. 419 * 420 * Return: Returns zero on success, nonzero on failure. 421 */ 422 static inline int ssam_device_register_clients(struct ssam_device *sdev) 423 { 424 return ssam_register_clients(&sdev->dev, sdev->ctrl); 425 } 426 427 428 /* -- Helpers for client-device requests. ----------------------------------- */ 429 430 /** 431 * SSAM_DEFINE_SYNC_REQUEST_CL_N() - Define synchronous client-device SAM 432 * request function with neither argument nor return value. 433 * @name: Name of the generated function. 434 * @spec: Specification (&struct ssam_request_spec_md) defining the request. 435 * 436 * Defines a function executing the synchronous SAM request specified by 437 * @spec, with the request having neither argument nor return value. Device 438 * specifying parameters are not hard-coded, but instead are provided via the 439 * client device, specifically its UID, supplied when calling this function. 440 * The generated function takes care of setting up the request struct, buffer 441 * allocation, as well as execution of the request itself, returning once the 442 * request has been fully completed. The required transport buffer will be 443 * allocated on the stack. 444 * 445 * The generated function is defined as ``static int name(struct ssam_device 446 * *sdev)``, returning the status of the request, which is zero on success and 447 * negative on failure. The ``sdev`` parameter specifies both the target 448 * device of the request and by association the controller via which the 449 * request is sent. 450 * 451 * Refer to ssam_request_do_sync_onstack() for more details on the behavior of 452 * the generated function. 453 */ 454 #define SSAM_DEFINE_SYNC_REQUEST_CL_N(name, spec...) \ 455 SSAM_DEFINE_SYNC_REQUEST_MD_N(__raw_##name, spec) \ 456 static int name(struct ssam_device *sdev) \ 457 { \ 458 return __raw_##name(sdev->ctrl, sdev->uid.target, \ 459 sdev->uid.instance); \ 460 } 461 462 /** 463 * SSAM_DEFINE_SYNC_REQUEST_CL_W() - Define synchronous client-device SAM 464 * request function with argument. 465 * @name: Name of the generated function. 466 * @atype: Type of the request's argument. 467 * @spec: Specification (&struct ssam_request_spec_md) defining the request. 468 * 469 * Defines a function executing the synchronous SAM request specified by 470 * @spec, with the request taking an argument of type @atype and having no 471 * return value. Device specifying parameters are not hard-coded, but instead 472 * are provided via the client device, specifically its UID, supplied when 473 * calling this function. The generated function takes care of setting up the 474 * request struct, buffer allocation, as well as execution of the request 475 * itself, returning once the request has been fully completed. The required 476 * transport buffer will be allocated on the stack. 477 * 478 * The generated function is defined as ``static int name(struct ssam_device 479 * *sdev, const atype *arg)``, returning the status of the request, which is 480 * zero on success and negative on failure. The ``sdev`` parameter specifies 481 * both the target device of the request and by association the controller via 482 * which the request is sent. The request's argument is specified via the 483 * ``arg`` pointer. 484 * 485 * Refer to ssam_request_do_sync_onstack() for more details on the behavior of 486 * the generated function. 487 */ 488 #define SSAM_DEFINE_SYNC_REQUEST_CL_W(name, atype, spec...) \ 489 SSAM_DEFINE_SYNC_REQUEST_MD_W(__raw_##name, atype, spec) \ 490 static int name(struct ssam_device *sdev, const atype *arg) \ 491 { \ 492 return __raw_##name(sdev->ctrl, sdev->uid.target, \ 493 sdev->uid.instance, arg); \ 494 } 495 496 /** 497 * SSAM_DEFINE_SYNC_REQUEST_CL_R() - Define synchronous client-device SAM 498 * request function with return value. 499 * @name: Name of the generated function. 500 * @rtype: Type of the request's return value. 501 * @spec: Specification (&struct ssam_request_spec_md) defining the request. 502 * 503 * Defines a function executing the synchronous SAM request specified by 504 * @spec, with the request taking no argument but having a return value of 505 * type @rtype. Device specifying parameters are not hard-coded, but instead 506 * are provided via the client device, specifically its UID, supplied when 507 * calling this function. The generated function takes care of setting up the 508 * request struct, buffer allocation, as well as execution of the request 509 * itself, returning once the request has been fully completed. The required 510 * transport buffer will be allocated on the stack. 511 * 512 * The generated function is defined as ``static int name(struct ssam_device 513 * *sdev, rtype *ret)``, returning the status of the request, which is zero on 514 * success and negative on failure. The ``sdev`` parameter specifies both the 515 * target device of the request and by association the controller via which 516 * the request is sent. The request's return value is written to the memory 517 * pointed to by the ``ret`` parameter. 518 * 519 * Refer to ssam_request_do_sync_onstack() for more details on the behavior of 520 * the generated function. 521 */ 522 #define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \ 523 SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \ 524 static int name(struct ssam_device *sdev, rtype *ret) \ 525 { \ 526 return __raw_##name(sdev->ctrl, sdev->uid.target, \ 527 sdev->uid.instance, ret); \ 528 } 529 530 /** 531 * SSAM_DEFINE_SYNC_REQUEST_CL_WR() - Define synchronous client-device SAM 532 * request function with argument and return value. 533 * @name: Name of the generated function. 534 * @atype: Type of the request's argument. 535 * @rtype: Type of the request's return value. 536 * @spec: Specification (&struct ssam_request_spec_md) defining the request. 537 * 538 * Defines a function executing the synchronous SAM request specified by @spec, 539 * with the request taking an argument of type @atype and having a return value 540 * of type @rtype. Device specifying parameters are not hard-coded, but instead 541 * are provided via the client device, specifically its UID, supplied when 542 * calling this function. The generated function takes care of setting up the 543 * request struct, buffer allocation, as well as execution of the request 544 * itself, returning once the request has been fully completed. The required 545 * transport buffer will be allocated on the stack. 546 * 547 * The generated function is defined as ``static int name(struct ssam_device 548 * *sdev, const atype *arg, rtype *ret)``, returning the status of the request, 549 * which is zero on success and negative on failure. The ``sdev`` parameter 550 * specifies both the target device of the request and by association the 551 * controller via which the request is sent. The request's argument is 552 * specified via the ``arg`` pointer. The request's return value is written to 553 * the memory pointed to by the ``ret`` parameter. 554 * 555 * Refer to ssam_request_do_sync_onstack() for more details on the behavior of 556 * the generated function. 557 */ 558 #define SSAM_DEFINE_SYNC_REQUEST_CL_WR(name, atype, rtype, spec...) \ 559 SSAM_DEFINE_SYNC_REQUEST_MD_WR(__raw_##name, atype, rtype, spec) \ 560 static int name(struct ssam_device *sdev, const atype *arg, rtype *ret) \ 561 { \ 562 return __raw_##name(sdev->ctrl, sdev->uid.target, \ 563 sdev->uid.instance, arg, ret); \ 564 } 565 566 567 /* -- Helpers for client-device notifiers. ---------------------------------- */ 568 569 /** 570 * ssam_device_notifier_register() - Register an event notifier for the 571 * specified client device. 572 * @sdev: The device the notifier should be registered on. 573 * @n: The event notifier to register. 574 * 575 * Register an event notifier. Increment the usage counter of the associated 576 * SAM event if the notifier is not marked as an observer. If the event is not 577 * marked as an observer and is currently not enabled, it will be enabled 578 * during this call. If the notifier is marked as an observer, no attempt will 579 * be made at enabling any event and no reference count will be modified. 580 * 581 * Notifiers marked as observers do not need to be associated with one specific 582 * event, i.e. as long as no event matching is performed, only the event target 583 * category needs to be set. 584 * 585 * Return: Returns zero on success, %-ENOSPC if there have already been 586 * %INT_MAX notifiers for the event ID/type associated with the notifier block 587 * registered, %-ENOMEM if the corresponding event entry could not be 588 * allocated, %-ENODEV if the device is marked as hot-removed. If this is the 589 * first time that a notifier block is registered for the specific associated 590 * event, returns the status of the event-enable EC-command. 591 */ 592 static inline int ssam_device_notifier_register(struct ssam_device *sdev, 593 struct ssam_event_notifier *n) 594 { 595 /* 596 * Note that this check does not provide any guarantees whatsoever as 597 * hot-removal could happen at any point and we can't protect against 598 * it. Nevertheless, if we can detect hot-removal, bail early to avoid 599 * communication timeouts. 600 */ 601 if (ssam_device_is_hot_removed(sdev)) 602 return -ENODEV; 603 604 return ssam_notifier_register(sdev->ctrl, n); 605 } 606 607 /** 608 * ssam_device_notifier_unregister() - Unregister an event notifier for the 609 * specified client device. 610 * @sdev: The device the notifier has been registered on. 611 * @n: The event notifier to unregister. 612 * 613 * Unregister an event notifier. Decrement the usage counter of the associated 614 * SAM event if the notifier is not marked as an observer. If the usage counter 615 * reaches zero, the event will be disabled. 616 * 617 * In case the device has been marked as hot-removed, the event will not be 618 * disabled on the EC, as in those cases any attempt at doing so may time out. 619 * 620 * Return: Returns zero on success, %-ENOENT if the given notifier block has 621 * not been registered on the controller. If the given notifier block was the 622 * last one associated with its specific event, returns the status of the 623 * event-disable EC-command. 624 */ 625 static inline int ssam_device_notifier_unregister(struct ssam_device *sdev, 626 struct ssam_event_notifier *n) 627 { 628 return __ssam_notifier_unregister(sdev->ctrl, n, 629 !ssam_device_is_hot_removed(sdev)); 630 } 631 632 #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */ 633
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.