diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index 26088886e2..559ed4b014 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -9095,3 +9095,47 @@ Example response: } } ~~ + +### framework_get_pci_devices + +List PCIe devices attached to an SPDK application and the contents of their config space. + +#### Parameters + +This method has no parameters. + +#### Response + +The response is an array of attached PCIe devices. + +#### Example + +Example request: +~~ +{ + "jsonrpc": "2.0", + "id": 1, + "method": "framework_get_pci_devices" +} +~~ + +Example response: +Note that the config space buffer was trimmed. +~~ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + [ + { + "address": "0000:00:04.0", + "config_space": "8680455807051000...0000000000000000" + }, + { + "address": "0000:00:03.0", + "config_space": "8680455807051000...0000000000000000" + } + ] + } +} +~~ diff --git a/lib/init/subsystem_rpc.c b/lib/init/subsystem_rpc.c index 3ff7fb376b..22b09aa99d 100644 --- a/lib/init/subsystem_rpc.c +++ b/lib/init/subsystem_rpc.c @@ -35,6 +35,7 @@ #include "spdk/string.h" #include "spdk/util.h" #include "spdk/env.h" +#include "spdk/log.h" #include "spdk_internal/init.h" @@ -119,3 +120,55 @@ rpc_framework_get_config(struct spdk_jsonrpc_request *request, SPDK_RPC_REGISTER("framework_get_config", rpc_framework_get_config, SPDK_RPC_RUNTIME) SPDK_RPC_REGISTER_ALIAS_DEPRECATED(framework_get_config, get_subsystem_config) + +static void +dump_pci_device(void *ctx, struct spdk_pci_device *dev) +{ + struct spdk_json_write_ctx *w = ctx; + struct spdk_pci_addr addr; + char config[4096], bdf[14]; + int rc; + + addr = spdk_pci_device_get_addr(dev); + spdk_pci_addr_fmt(bdf, sizeof(bdf), &addr); + + rc = spdk_pci_device_cfg_read(dev, config, sizeof(config), 0); + if (rc != 0) { + SPDK_ERRLOG("Failed to read config space of device: %s\n", bdf); + return; + } + + spdk_json_write_object_begin(w); + spdk_json_write_named_string(w, "address", bdf); + + /* Don't write the extended config space if it's all zeroes */ + if (spdk_mem_all_zero(&config[256], sizeof(config) - 256)) { + spdk_json_write_named_bytearray(w, "config_space", config, 256); + } else { + spdk_json_write_named_bytearray(w, "config_space", config, sizeof(config)); + } + + spdk_json_write_object_end(w); +} + +static void +rpc_framework_get_pci_devices(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct spdk_json_write_ctx *w; + + if (params != NULL) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "framework_get_pci_devices doesn't accept any parameters.\n"); + return; + } + + w = spdk_jsonrpc_begin_result(request); + + spdk_json_write_array_begin(w); + spdk_pci_for_each_device(w, dump_pci_device); + spdk_json_write_array_end(w); + + spdk_jsonrpc_end_result(request, w); +} +SPDK_RPC_REGISTER("framework_get_pci_devices", rpc_framework_get_pci_devices, SPDK_RPC_RUNTIME) diff --git a/scripts/rpc.py b/scripts/rpc.py index 8a305a07d9..6a64f8c87a 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -2690,6 +2690,12 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) p.set_defaults(func=sock_set_default_impl) + def framework_get_pci_devices(args): + print_json(rpc.subsystem.framework_get_pci_devices(args.client)) + + p = subparsers.add_parser('framework_get_pci_devices', help='''Get a list of attached PCI devices''') + p.set_defaults(func=framework_get_pci_devices) + def check_called_name(name): if name in deprecated_aliases: print("{} is deprecated, use {} instead.".format(name, deprecated_aliases[name]), file=sys.stderr) diff --git a/scripts/rpc/subsystem.py b/scripts/rpc/subsystem.py index a52adbf6b9..fe948913cf 100644 --- a/scripts/rpc/subsystem.py +++ b/scripts/rpc/subsystem.py @@ -10,3 +10,7 @@ def framework_get_subsystems(client): def framework_get_config(client, name): params = {'name': name} return client.call('framework_get_config', params) + + +def framework_get_pci_devices(client): + return client.call('framework_get_pci_devices')