1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Direct Internal Buffer Sharing 4 * 5 * Definitions for the DIBS module 6 * 7 * Copyright IBM Corp. 2025 8 */ 9 #ifndef _DIBS_H 10 #define _DIBS_H 11 12 #include <linux/device.h> 13 #include <linux/uuid.h> 14 15 /* DIBS - Direct Internal Buffer Sharing - concept 16 * ----------------------------------------------- 17 * In the case of multiple system sharing the same hardware, dibs fabrics can 18 * provide dibs devices to these systems. The systems use dibs devices of the 19 * same fabric to communicate via dmbs (Direct Memory Buffers). Each dmb has 20 * exactly one owning local dibs device and one remote using dibs device, that 21 * is authorized to write into this dmb. This access control is provided by the 22 * dibs fabric. 23 * 24 * Because the access to the dmb is based on access to physical memory, it is 25 * lossless and synchronous. The remote devices can directly access any offset 26 * of the dmb. 27 * 28 * Dibs fabrics, dibs devices and dmbs are identified by tokens and ids. 29 * Dibs fabric id is unique within the same hardware (with the exception of the 30 * dibs loopback fabric), dmb token is unique within the same fabric, dibs 31 * device gids are guaranteed to be unique within the same fabric and 32 * statistically likely to be globally unique. The exchange of these tokens and 33 * ids between the systems is not part of the dibs concept. 34 * 35 * The dibs layer provides an abstraction between dibs device drivers and dibs 36 * clients. 37 */ 38 39 /* DMB - Direct Memory Buffer 40 * -------------------------- 41 * A dibs client provides a dmb as input buffer for a local receiving 42 * dibs device for exactly one (remote) sending dibs device. Only this 43 * sending device can send data into this dmb using move_data(). Sender 44 * and receiver can be the same device. A dmb belongs to exactly one client. 45 */ 46 struct dibs_dmb { 47 /* tok - Token for this dmb 48 * Used by remote and local devices and clients to address this dmb. 49 * Provided by dibs fabric. Unique per dibs fabric. 50 */ 51 u64 dmb_tok; 52 /* rgid - GID of designated remote sending device */ 53 uuid_t rgid; 54 /* cpu_addr - buffer address */ 55 void *cpu_addr; 56 /* len - buffer length */ 57 u32 dmb_len; 58 /* idx - Index of this DMB on this receiving device */ 59 u32 idx; 60 /* VLAN support (deprecated) 61 * In order to write into a vlan-tagged dmb, the remote device needs 62 * to belong to the this vlan 63 */ 64 u32 vlan_valid; 65 u32 vlan_id; 66 /* optional, used by device driver */ 67 dma_addr_t dma_addr; 68 }; 69 70 /* DIBS events 71 * ----------- 72 * Dibs devices can optionally notify dibs clients about events that happened 73 * in the fabric or at the remote device or remote dmb. 74 */ 75 enum dibs_event_type { 76 /* Buffer event, e.g. a remote dmb was unregistered */ 77 DIBS_BUF_EVENT, 78 /* Device event, e.g. a remote dibs device was disabled */ 79 DIBS_DEV_EVENT, 80 /* Software event, a dibs client can send an event signal to a 81 * remote dibs device. 82 */ 83 DIBS_SW_EVENT, 84 DIBS_OTHER_TYPE }; 85 86 enum dibs_event_subtype { 87 DIBS_BUF_UNREGISTERED, 88 DIBS_DEV_DISABLED, 89 DIBS_DEV_ERR_STATE, 90 DIBS_OTHER_SUBTYPE 91 }; 92 93 struct dibs_event { 94 u32 type; 95 u32 subtype; 96 /* uuid_null if invalid */ 97 uuid_t gid; 98 /* zero if invalid */ 99 u64 buffer_tok; 100 u64 time; 101 /* additional data or zero */ 102 u64 data; 103 }; 104 105 struct dibs_dev; 106 107 /* DIBS client 108 * ----------- 109 */ 110 #define MAX_DIBS_CLIENTS 8 111 #define NO_DIBS_CLIENT 0xff 112 /* All dibs clients have access to all dibs devices. 113 * A dibs client provides the following functions to be called by dibs layer or 114 * dibs device drivers: 115 */ 116 struct dibs_client_ops { 117 /** 118 * add_dev() - add a dibs device 119 * @dev: device that was added 120 * 121 * Will be called during dibs_register_client() for all existing 122 * dibs devices and whenever a new dibs device is registered. 123 * dev is usable until dibs_client.remove() is called. 124 * *dev is protected by device refcounting. 125 */ 126 void (*add_dev)(struct dibs_dev *dev); 127 /** 128 * del_dev() - remove a dibs device 129 * @dev: device to be removed 130 * 131 * Will be called whenever a dibs device is removed. 132 * Will be called during dibs_unregister_client() for all existing 133 * dibs devices and whenever a dibs device is unregistered. 134 * The device has already stopped initiative for this client: 135 * No new handlers will be started. 136 * The device is no longer usable by this client after this call. 137 */ 138 void (*del_dev)(struct dibs_dev *dev); 139 /** 140 * handle_irq() - Handle signaling for a DMB 141 * @dev: device that owns the dmb 142 * @idx: Index of the dmb that got signalled 143 * @dmbemask: signaling mask of the dmb 144 * 145 * Handle signaling for a dmb that was registered by this client 146 * for this device. 147 * The dibs device can coalesce multiple signaling triggers into a 148 * single call of handle_irq(). dmbemask can be used to indicate 149 * different kinds of triggers. 150 * 151 * Context: Called in IRQ context by dibs device driver 152 */ 153 void (*handle_irq)(struct dibs_dev *dev, unsigned int idx, 154 u16 dmbemask); 155 /** 156 * handle_event() - Handle control information sent by device 157 * @dev: device reporting the event 158 * @event: ism event structure 159 * 160 * * Context: Called in IRQ context by dibs device driver 161 */ 162 void (*handle_event)(struct dibs_dev *dev, 163 const struct dibs_event *event); 164 }; 165 166 struct dibs_client { 167 /* client name for logging and debugging purposes */ 168 const char *name; 169 const struct dibs_client_ops *ops; 170 /* client index - provided and used by dibs layer */ 171 u8 id; 172 }; 173 174 /* Functions to be called by dibs clients: 175 */ 176 /** 177 * dibs_register_client() - register a client with dibs layer 178 * @client: this client 179 * 180 * Will call client->ops->add_dev() for all existing dibs devices. 181 * Return: zero on success. 182 */ 183 int dibs_register_client(struct dibs_client *client); 184 /** 185 * dibs_unregister_client() - unregister a client with dibs layer 186 * @client: this client 187 * 188 * Will call client->ops->del_dev() for all existing dibs devices. 189 * Return: zero on success. 190 */ 191 int dibs_unregister_client(struct dibs_client *client); 192 193 /* dibs clients can call dibs device ops. */ 194 195 /* DIBS devices 196 * ------------ 197 */ 198 199 /* Defined fabric id / CHID for all loopback devices: 200 * All dibs loopback devices report this fabric id. In this case devices with 201 * the same fabric id can NOT communicate via dibs. Only loopback devices with 202 * the same dibs device gid can communicate (=same device with itself). 203 */ 204 #define DIBS_LOOPBACK_FABRIC 0xFFFF 205 206 /* A dibs device provides the following functions to be called by dibs clients. 207 * They are mandatory, unless marked 'optional'. 208 */ 209 struct dibs_dev_ops { 210 /** 211 * get_fabric_id() 212 * @dev: local dibs device 213 * 214 * Only devices on the same dibs fabric can communicate. Fabric_id is 215 * unique inside the same HW system. Use fabric_id for fast negative 216 * checks, but only query_remote_gid() can give a reliable positive 217 * answer: 218 * Different fabric_id: dibs is not possible 219 * Same fabric_id: dibs may be possible or not 220 * (e.g. different HW systems) 221 * EXCEPTION: DIBS_LOOPBACK_FABRIC denotes an ism_loopback device 222 * that can only communicate with itself. Use dibs_dev.gid 223 * or query_remote_gid()to determine whether sender and 224 * receiver use the same ism_loopback device. 225 * Return: 2 byte dibs fabric id 226 */ 227 u16 (*get_fabric_id)(struct dibs_dev *dev); 228 /** 229 * query_remote_gid() 230 * @dev: local dibs device 231 * @rgid: gid of remote dibs device 232 * @vid_valid: if zero, vid will be ignored; 233 * deprecated, ignored if device does not support vlan 234 * @vid: VLAN id; deprecated, ignored if device does not support vlan 235 * 236 * Query whether a remote dibs device is reachable via this local device 237 * and this vlan id. 238 * Return: 0 if remote gid is reachable. 239 */ 240 int (*query_remote_gid)(struct dibs_dev *dev, const uuid_t *rgid, 241 u32 vid_valid, u32 vid); 242 /** 243 * max_dmbs() 244 * Return: Max number of DMBs that can be registered for this kind of 245 * dibs_dev 246 */ 247 int (*max_dmbs)(void); 248 /** 249 * register_dmb() - allocate and register a dmb 250 * @dev: dibs device 251 * @dmb: dmb struct to be registered 252 * @client: dibs client 253 * @vid: VLAN id; deprecated, ignored if device does not support vlan 254 * 255 * The following fields of dmb must provide valid input: 256 * @rgid: gid of remote user device 257 * @dmb_len: buffer length 258 * @idx: Optionally:requested idx (if non-zero) 259 * @vlan_valid: if zero, vlan_id will be ignored; 260 * deprecated, ignored if device does not support vlan 261 * @vlan_id: deprecated, ignored if device does not support vlan 262 * Upon return in addition the following fields will be valid: 263 * @dmb_tok: for usage by remote and local devices and clients 264 * @cpu_addr: allocated buffer 265 * @idx: dmb index, unique per dibs device 266 * @dma_addr: to be used by device driver,if applicable 267 * 268 * Allocate a dmb buffer and register it with this device and for this 269 * client. 270 * Return: zero on success 271 */ 272 int (*register_dmb)(struct dibs_dev *dev, struct dibs_dmb *dmb, 273 struct dibs_client *client); 274 /** 275 * unregister_dmb() - unregister and free a dmb 276 * @dev: dibs device 277 * @dmb: dmb struct to be unregistered 278 * The following fields of dmb must provide valid input: 279 * @dmb_tok 280 * @cpu_addr 281 * @idx 282 * 283 * Free dmb.cpu_addr and unregister the dmb from this device. 284 * Return: zero on success 285 */ 286 int (*unregister_dmb)(struct dibs_dev *dev, struct dibs_dmb *dmb); 287 /** 288 * move_data() - write into a remote dmb 289 * @dev: Local sending dibs device 290 * @dmb_tok: Token of the remote dmb 291 * @idx: signaling index in dmbemask 292 * @sf: signaling flag; 293 * if true, idx will be turned on at target dmbemask mask 294 * and target device will be signaled. 295 * @offset: offset within target dmb 296 * @data: pointer to data to be sent 297 * @size: length of data to be sent, can be zero. 298 * 299 * Use dev to write data of size at offset into a remote dmb 300 * identified by dmb_tok. Data is moved synchronously, *data can 301 * be freed when this function returns. 302 * 303 * If signaling flag (sf) is true, bit number idx bit will be turned 304 * on in the dmbemask mask when handle_irq() is called at the remote 305 * dibs client that owns the target dmb. The target device may chose 306 * to coalesce the signaling triggers of multiple move_data() calls 307 * to the same target dmb into a single handle_irq() call. 308 * Return: zero on success 309 */ 310 int (*move_data)(struct dibs_dev *dev, u64 dmb_tok, unsigned int idx, 311 bool sf, unsigned int offset, void *data, 312 unsigned int size); 313 /** 314 * add_vlan_id() - add dibs device to vlan (optional, deprecated) 315 * @dev: dibs device 316 * @vlan_id: vlan id 317 * 318 * In order to write into a vlan-tagged dmb, the remote device needs 319 * to belong to the this vlan. A device can belong to more than 1 vlan. 320 * Any device can access an untagged dmb. 321 * Deprecated, only supported for backwards compatibility. 322 * Return: zero on success 323 */ 324 int (*add_vlan_id)(struct dibs_dev *dev, u64 vlan_id); 325 /** 326 * del_vlan_id() - remove dibs device from vlan (optional, deprecated) 327 * @dev: dibs device 328 * @vlan_id: vlan id 329 * Return: zero on success 330 */ 331 int (*del_vlan_id)(struct dibs_dev *dev, u64 vlan_id); 332 /** 333 * signal_event() - trigger an event at a remote dibs device (optional) 334 * @dev: local dibs device 335 * @rgid: gid of remote dibs device 336 * trigger_irq: zero: notification may be coalesced with other events 337 * non-zero: notify immediately 338 * @subtype: 4 byte event code, meaning is defined by dibs client 339 * @data: 8 bytes of additional information, 340 * meaning is defined by dibs client 341 * 342 * dibs devices can offer support for sending a control event of type 343 * EVENT_SWR to a remote dibs device. 344 * NOTE: handle_event() will be called for all registered dibs clients 345 * at the remote device. 346 * Return: zero on success 347 */ 348 int (*signal_event)(struct dibs_dev *dev, const uuid_t *rgid, 349 u32 trigger_irq, u32 event_code, u64 info); 350 /** 351 * support_mmapped_rdmb() - can this device provide memory mapped 352 * remote dmbs? (optional) 353 * @dev: dibs device 354 * 355 * A dibs device can provide a kernel address + length, that represent 356 * a remote target dmb (like MMIO). Alternatively to calling 357 * move_data(), a dibs client can write into such a ghost-send-buffer 358 * (= to this kernel address) and the data will automatically 359 * immediately appear in the target dmb, even without calling 360 * move_data(). 361 * 362 * Either all 3 function pointers for support_dmb_nocopy(), 363 * attach_dmb() and detach_dmb() are defined, or all of them must 364 * be NULL. 365 * 366 * Return: non-zero, if memory mapped remote dmbs are supported. 367 */ 368 int (*support_mmapped_rdmb)(struct dibs_dev *dev); 369 /** 370 * attach_dmb() - attach local memory to a remote dmb 371 * @dev: Local sending ism device 372 * @dmb: all other parameters are passed in the form of a 373 * dmb struct 374 * TODO: (THIS IS CONFUSING, should be changed) 375 * dmb_tok: (in) Token of the remote dmb, we want to attach to 376 * cpu_addr: (out) MMIO address 377 * dma_addr: (out) MMIO address (if applicable, invalid otherwise) 378 * dmb_len: (out) length of local MMIO region, 379 * equal to length of remote DMB. 380 * sba_idx: (out) index of remote dmb (NOT HELPFUL, should be removed) 381 * 382 * Provides a memory address to the sender that can be used to 383 * directly write into the remote dmb. 384 * Memory is available until detach_dmb is called 385 * 386 * Return: Zero upon success, Error code otherwise 387 */ 388 int (*attach_dmb)(struct dibs_dev *dev, struct dibs_dmb *dmb); 389 /** 390 * detach_dmb() - Detach the ghost buffer from a remote dmb 391 * @dev: ism device 392 * @token: dmb token of the remote dmb 393 * 394 * No need to free cpu_addr. 395 * 396 * Return: Zero upon success, Error code otherwise 397 */ 398 int (*detach_dmb)(struct dibs_dev *dev, u64 token); 399 }; 400 401 struct dibs_dev { 402 struct list_head list; 403 struct device dev; 404 /* To be filled by device driver, before calling dibs_dev_add(): */ 405 const struct dibs_dev_ops *ops; 406 uuid_t gid; 407 /* priv pointer for device driver */ 408 void *drv_priv; 409 410 /* priv pointer per client; for client usage only */ 411 void *priv[MAX_DIBS_CLIENTS]; 412 413 /* get this lock before accessing any of the fields below */ 414 spinlock_t lock; 415 /* array of client ids indexed by dmb idx; 416 * can be used as indices into priv and subs arrays 417 */ 418 u8 *dmb_clientid_arr; 419 /* Sparse array of all ISM clients */ 420 struct dibs_client *subs[MAX_DIBS_CLIENTS]; 421 }; 422 423 static inline void dibs_set_priv(struct dibs_dev *dev, 424 struct dibs_client *client, void *priv) 425 { 426 dev->priv[client->id] = priv; 427 } 428 429 static inline void *dibs_get_priv(struct dibs_dev *dev, 430 struct dibs_client *client) 431 { 432 return dev->priv[client->id]; 433 } 434 435 /* ------- End of client-only functions ----------- */ 436 437 /* Functions to be called by dibs device drivers: 438 */ 439 /** 440 * dibs_dev_alloc() - allocate and reference device structure 441 * 442 * The following fields will be valid upon successful return: dev 443 * NOTE: Use put_device(dibs_get_dev(@dibs)) to give up your reference instead 444 * of freeing @dibs @dev directly once you have successfully called this 445 * function. 446 * Return: Pointer to dibs device structure 447 */ 448 struct dibs_dev *dibs_dev_alloc(void); 449 /** 450 * dibs_dev_add() - register with dibs layer and all clients 451 * @dibs: dibs device 452 * 453 * The following fields must be valid upon entry: dev, ops, drv_priv 454 * All fields will be valid upon successful return. 455 * Return: zero on success 456 */ 457 int dibs_dev_add(struct dibs_dev *dibs); 458 /** 459 * dibs_dev_del() - unregister from dibs layer and all clients 460 * @dibs: dibs device 461 */ 462 void dibs_dev_del(struct dibs_dev *dibs); 463 464 #endif /* _DIBS_H */ 465