diff --git a/pyverbs/device.pyx b/pyverbs/device.pyx index 054f8b4d4..137eb0c48 100644 --- a/pyverbs/device.pyx +++ b/pyverbs/device.pyx @@ -266,6 +266,18 @@ cdef class Context(PyverbsCM): format(p=port_num), rc) return port_attrs + def query_port_speed(self, unsigned int port_num): + """ + Query port speed in 100 Mb/s granularity. + :param port_num: Port number to query + :return: Port speed + """ + cdef uint64_t port_speed + rc = v.ibv_query_port_speed(self.context, port_num, &port_speed) + if rc != 0: + raise PyverbsRDMAError(f'Failed to query port speed for port {port_num}', rc) + return port_speed + def query_gid_table(self, size_t max_entries, uint32_t flags=0): """ Queries the GID tables of the device for at most entries @@ -854,6 +866,16 @@ cdef class DM(PyverbsCM): free(data) return res + def export_dmabuf_fd(self): + """ + Export a dmabuf FD for this DM object. + :return: A file descriptor (int) for the dmabuf FD + """ + fd = v.ibv_dm_export_dmabuf_fd(self.dm) + if fd < 0: + raise PyverbsRDMAErrno('Failed to export dmabuf FD for DM') + return fd + @property def handle(self): return self.dm.handle @@ -1266,7 +1288,8 @@ def translate_event_type(event_type): e.IBV_EVENT_QP_LAST_WQE_REACHED: '.IBV_EVENT_QP_LAST_WQE_REACHED', e.IBV_EVENT_CLIENT_REREGISTER: 'IBV_EVENT_CLIENT_REREGISTER', e.IBV_EVENT_GID_CHANGE: 'IBV_EVENT_GID_CHANGE', - e.IBV_EVENT_WQ_FATAL: 'IBV_EVENT_WQ_FATAL' + e.IBV_EVENT_WQ_FATAL: 'IBV_EVENT_WQ_FATAL', + e.IBV_EVENT_DEVICE_SPEED_CHANGE: 'IBV_EVENT_DEVICE_SPEED_CHANGE' } try: return types[event_type] diff --git a/pyverbs/libibverbs.pxd b/pyverbs/libibverbs.pxd index 18889f561..96b4b098d 100644 --- a/pyverbs/libibverbs.pxd +++ b/pyverbs/libibverbs.pxd @@ -703,8 +703,11 @@ cdef extern from 'infiniband/verbs.h': size_t length) int ibv_memcpy_from_dm(void *host_addr, ibv_dm *dm, unsigned long dm_offset, size_t length) + int ibv_dm_export_dmabuf_fd(ibv_dm *dm) int ibv_query_port(ibv_context *context, uint8_t port_num, ibv_port_attr *port_attr) + int ibv_query_port_speed(ibv_context *context, uint8_t port_num, + uint64_t *port_speed) ibv_comp_channel *ibv_create_comp_channel(ibv_context *context) int ibv_destroy_comp_channel(ibv_comp_channel *channel) int ibv_get_cq_event(ibv_comp_channel *channel, ibv_cq **cq, diff --git a/pyverbs/libibverbs_enums.pxd b/pyverbs/libibverbs_enums.pxd index aae55d1c3..e7caf854b 100644 --- a/pyverbs/libibverbs_enums.pxd +++ b/pyverbs/libibverbs_enums.pxd @@ -104,6 +104,7 @@ cdef extern from '': IBV_EVENT_CLIENT_REREGISTER IBV_EVENT_GID_CHANGE IBV_EVENT_WQ_FATAL + IBV_EVENT_DEVICE_SPEED_CHANGE cpdef enum ibv_access_flags: IBV_ACCESS_LOCAL_WRITE diff --git a/pyverbs/providers/mlx5/libmlx5.pxd b/pyverbs/providers/mlx5/libmlx5.pxd index ac415de6a..0faa439ed 100644 --- a/pyverbs/providers/mlx5/libmlx5.pxd +++ b/pyverbs/providers/mlx5/libmlx5.pxd @@ -568,6 +568,7 @@ cdef extern from 'infiniband/mlx5dv.h': # DevX APIs mlx5dv_devx_uar *mlx5dv_devx_alloc_uar(v.ibv_context *context, uint32_t flags) void mlx5dv_devx_free_uar(mlx5dv_devx_uar *devx_uar) + int mlx5dv_devx_uar_export_dmabuf_fd(mlx5dv_devx_uar *devx_uar) int mlx5dv_devx_general_cmd(v.ibv_context *context, const void *in_, size_t inlen, void *out, size_t outlen) mlx5dv_devx_umem *mlx5dv_devx_umem_reg(v.ibv_context *ctx, void *addr, diff --git a/pyverbs/providers/mlx5/mlx5dv.pyx b/pyverbs/providers/mlx5/mlx5dv.pyx index a4635827b..f14118821 100644 --- a/pyverbs/providers/mlx5/mlx5dv.pyx +++ b/pyverbs/providers/mlx5/mlx5dv.pyx @@ -1455,6 +1455,16 @@ cdef class Mlx5UAR(PyverbsObject): def uar(self): return self.uar + def export_dmabuf_fd(self): + """ + Export a dmabuf FD for this UAR object. + :return: A file descriptor (int) for the dmabuf FD + """ + fd = dv.mlx5dv_devx_uar_export_dmabuf_fd(self.uar) + if fd < 0: + raise PyverbsRDMAErrno('Failed to export dmabuf FD for UAR') + return fd + cdef class Mlx5DmOpAddr(PyverbsCM): def __init__(self, DM dm not None, op=0): diff --git a/tests/test_device.py b/tests/test_device.py index 411a49529..a56fa8614 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -284,6 +284,22 @@ def test_query_port_bad_flow(self): 'Successfully queried non-existing port {p}'. \ format(p=port)) + def test_query_port_speed(self): + """ + Test ibv_query_port_speed + """ + for dev in self.get_device_list(): + with d.Context(name=dev.name.decode()) as ctx: + try: + port_speed = ctx.query_port_speed(self.ib_port) + except PyverbsRDMAError as ex: + if ex.error_code in [errno.EOPNOTSUPP, errno.EPROTONOSUPPORT]: + raise unittest.SkipTest('ibv_query_port_speed is not' + ' supported on this device') + raise ex + self.assertGreaterEqual(port_speed, 0, 'Port speed should be positive, got' + f' {port_speed} Mbps') + class DMTest(PyverbsAPITestCase): """ diff --git a/tests/test_mlx5_uar.py b/tests/test_mlx5_uar.py index 44a626727..d6f3ce87d 100644 --- a/tests/test_mlx5_uar.py +++ b/tests/test_mlx5_uar.py @@ -36,3 +36,17 @@ def test_alloc_uar(self): finally: for uar in self.uar_res.uars: uar.close() + + def test_uar_export_dmabuf_fd(self): + """Test exporting a UAR as a dmabuf FD""" + try: + self.uar_res.uars.append(Mlx5UAR(self.uar_res.ctx, _MLX5DV_UAR_ALLOC_TYPE_NC)) + dmabuf_fd = self.uar_res.uars[-1].export_dmabuf_fd() + self.assertGreater(dmabuf_fd, 0, 'Expected a valid dmabuf FD greater than 0') + except PyverbsRDMAError as ex: + if ex.error_code in [errno.EPROTONOSUPPORT, errno.EOPNOTSUPP]: + raise unittest.SkipTest('UAR dmabuf export is not supported') + raise ex + finally: + for uar in self.uar_res.uars: + uar.close() diff --git a/tests/test_mr.py b/tests/test_mr.py index fdde078e9..ef75f4b24 100644 --- a/tests/test_mr.py +++ b/tests/test_mr.py @@ -484,6 +484,18 @@ def test_dm_bad_registration(self): with self.assertRaisesRegex(PyverbsRDMAError, 'Failed to register a device MR'): DMMR(PD(self.ctx), dm_size + 4, dm_access, dm, 0) + def test_dm_export_dmabuf_fd(self): + """Test exporting a DM as a dmabuf FD""" + dm_size = 100 + try: + with d.DM(self.ctx, d.AllocDmAttr(length=dm_size)) as dm: + dmabuf_fd = dm.export_dmabuf_fd() + self.assertGreater(dmabuf_fd, 0, 'Expected a valid dmabuf FD greater than 0') + except PyverbsRDMAError as ex: + if ex.error_code in [errno.EOPNOTSUPP, errno.EPROTONOSUPPORT]: + raise unittest.SkipTest('DM dmabuf export is not supported') + raise ex + def check_dmabuf_support(gpu=0): """