aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSwapnil Ingle <swapnil.ingle@nutanix.com>2021-05-25 15:25:35 +0200
committerGitHub <noreply@github.com>2021-05-25 15:25:35 +0200
commit405f2ffc3125d44c7fde31fe2bb9b312746eb4e1 (patch)
treee2ab2e95b859e71010a574815ba0664a35b02789
parentf74a146a6b93f7bd366853739d8ec0dfc9c4a48f (diff)
downloadlibvfio-user-405f2ffc3125d44c7fde31fe2bb9b312746eb4e1.zip
libvfio-user-405f2ffc3125d44c7fde31fe2bb9b312746eb4e1.tar.gz
libvfio-user-405f2ffc3125d44c7fde31fe2bb9b312746eb4e1.tar.bz2
Handle support of PCI FLR capability (#517)
* Handle support of PCI FLR capability If device supports FLR cap then call vfu_reset_cb_t when FLR is initiated by client. Signed-off-by: Swapnil Ingle <swapnil.ingle@nutanix.com> Reviewed-by: John Levon <john.levon@nutanix.com> Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
-rw-r--r--include/libvfio-user.h8
-rw-r--r--lib/pci_caps.c12
-rw-r--r--test/py/libvfio_user.py12
-rw-r--r--test/py/test_pci_caps.py32
4 files changed, 58 insertions, 6 deletions
diff --git a/include/libvfio-user.h b/include/libvfio-user.h
index 6cb817d..009ba83 100644
--- a/include/libvfio-user.h
+++ b/include/libvfio-user.h
@@ -317,12 +317,18 @@ typedef enum vfu_reset_type {
* reset to a known-good initial state (including any PCI register state).
*/
VFU_RESET_DEVICE,
+
/*
* The vfio-user socket client connection was closed or reset. The attached
* context is cleaned up after returning from the reset callback, and
* vfu_attach_ctx() must be called to establish a new client.
*/
- VFU_RESET_LOST_CONN
+ VFU_RESET_LOST_CONN,
+
+ /*
+ * Client requested to initiate PCI function level reset.
+ */
+ VFU_RESET_PCI_FLR
} vfu_reset_type_t;
/*
diff --git a/lib/pci_caps.c b/lib/pci_caps.c
index 550d373..b00b9b8 100644
--- a/lib/pci_caps.c
+++ b/lib/pci_caps.c
@@ -277,8 +277,16 @@ handle_px_pxdc_write(vfu_ctx_t *vfu_ctx, struct pxcap *px,
}
if (p->iflr) {
- vfu_log(vfu_ctx, LOG_DEBUG,
- "initiate function level reset");
+ if (px->pxdcap.flrc == 0) {
+ vfu_log(vfu_ctx, LOG_ERR, "FLR capability is not supported");
+ return ERROR_INT(EINVAL);
+ }
+ if (vfu_ctx->reset != NULL) {
+ vfu_log(vfu_ctx, LOG_DEBUG, "initiate function level reset");
+ return vfu_ctx->reset(vfu_ctx, VFU_RESET_PCI_FLR);
+ } else {
+ vfu_log(vfu_ctx, LOG_ERR, "FLR callback is not implemented");
+ }
}
return 0;
diff --git a/test/py/libvfio_user.py b/test/py/libvfio_user.py
index 930c88a..d53740a 100644
--- a/test/py/libvfio_user.py
+++ b/test/py/libvfio_user.py
@@ -58,6 +58,7 @@ PCI_CAP_LIST_NEXT = 1
PCI_CAP_ID_PM = 0x1
PCI_CAP_ID_VNDR = 0x9
+PCI_CAP_ID_EXP = 0x10
PCI_EXT_CAP_ID_DSN = 0x03
PCI_EXT_CAP_ID_VNDR = 0x0b
@@ -151,6 +152,11 @@ VFU_DEV_ERR_IRQ = 3
VFU_DEV_REQ_IRQ = 4
VFU_DEV_NUM_IRQS = 5
+# enum vfu_reset_type
+VFU_RESET_DEVICE = 0
+VFU_RESET_LOST_CONN = 1
+VFU_RESET_PCI_FLR = 2
+
# vfu_pci_type_t
VFU_PCI_TYPE_CONVENTIONAL = 0
VFU_PCI_TYPE_PCI_X_1 = 1
@@ -234,6 +240,8 @@ vfu_region_access_cb_t = c.CFUNCTYPE(c.c_int, c.c_void_p, c.POINTER(c.c_char),
lib.vfu_setup_region.argtypes = (c.c_void_p, c.c_int, c.c_ulong,
vfu_region_access_cb_t, c.c_int, c.c_void_p,
c.c_uint32, c.c_int, c.c_ulong)
+vfu_reset_cb_t = c.CFUNCTYPE(c.c_int, c.c_void_p, c.c_int)
+lib.vfu_setup_device_reset_cb.argtypes = (c.c_void_p, vfu_reset_cb_t)
lib.vfu_pci_get_config_space.argtypes = (c.c_void_p,)
lib.vfu_pci_get_config_space.restype = (c.c_void_p)
lib.vfu_setup_device_nr_irqs.argtypes = (c.c_void_p, c.c_int, c.c_uint32)
@@ -457,6 +465,10 @@ def vfu_setup_region(ctx, index, size, cb=None, flags=0,
return ret
+def vfu_setup_device_reset_cb(ctx, cb):
+ assert ctx != None
+ return lib.vfu_setup_device_reset_cb(ctx, c.cast(cb, vfu_reset_cb_t))
+
def vfu_setup_device_nr_irqs(ctx, irqtype, count):
assert ctx != None
return lib.vfu_setup_device_nr_irqs(ctx, irqtype, count)
diff --git a/test/py/test_pci_caps.py b/test/py/test_pci_caps.py
index 9691fe1..d510727 100644
--- a/test/py/test_pci_caps.py
+++ b/test/py/test_pci_caps.py
@@ -100,7 +100,8 @@ cap_offsets = (
# NB: note 4-byte alignment of vsc2
PCI_STD_HEADER_SIZEOF + PCI_PM_SIZEOF + 8,
0x80,
- 0x90
+ 0x90,
+ 0xa0
)
def test_add_caps():
@@ -293,9 +294,34 @@ def test_pci_cap_write_pmcs():
disconnect_client(ctx, sock)
+reset_flag = -1
+@c.CFUNCTYPE(c.c_int, c.c_void_p, c.c_int)
+def vfu_reset_cb(ctx, reset_type):
+ assert reset_type == VFU_RESET_PCI_FLR or reset_type == VFU_RESET_LOST_CONN
+ global reset_flag
+ reset_flag = reset_type
+ return 0
+
def test_pci_cap_write_px():
- # FIXME
- pass
+ sock = connect_client(ctx)
+ ret = vfu_setup_device_reset_cb(ctx, vfu_reset_cb)
+ assert ret == 0
+
+ #flrc
+ cap = struct.pack("ccHHcc52c", to_byte(PCI_CAP_ID_EXP), b'\0', 0, 0, b'\0',
+ b'\x02', *[b'\0' for _ in range(52)])
+ pos = vfu_pci_add_capability(ctx, pos=cap_offsets[5], flags=0, data=cap)
+ assert pos == cap_offsets[5]
+
+ #iflr
+ offset = cap_offsets[5] + 8
+ data = b'\x00\x80'
+ write_region(ctx, sock, VFU_PCI_DEV_CFG_REGION_IDX, offset=offset,
+ count=len(data), data=data)
+ assert reset_flag == VFU_RESET_PCI_FLR
+
+ disconnect_client(ctx, sock)
+ assert reset_flag == VFU_RESET_LOST_CONN
def test_pci_cap_write_msix():
# FIXME