xref: /linux/include/linux/dibs.h (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
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