File Index
Files and directories
Sign in
FILE

dibs.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/dibs.h C
  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 */
 46struct 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 */
 75enum 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
 86enum dibs_event_subtype {
 87	DIBS_BUF_UNREGISTERED,
 88	DIBS_DEV_DISABLED,
 89	DIBS_DEV_ERR_STATE,
 90	DIBS_OTHER_SUBTYPE
 91};
 92
 93struct 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
105struct 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 */
116struct 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
166struct 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 */
183int 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 */
191int 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 */
209struct 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
401struct 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
423static 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
429static 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 */
448struct 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 */
457int dibs_dev_add(struct dibs_dev *dibs);
458/**
459 * dibs_dev_del() - unregister from dibs layer and all clients
460 * @dibs: dibs device
461 */
462void dibs_dev_del(struct dibs_dev *dibs);
463
464#endif	/* _DIBS_H */
~/ Read-only file preview.