xref: /dpdk/drivers/dma/idxd/dpdk_idxd_cfg.py (revision d569af3d4e8ef896591f4e50f7bd1c1274c86e15)
18bedc515SConor Walsh#!/usr/bin/env python3
28bedc515SConor Walsh# SPDX-License-Identifier: BSD-3-Clause
38bedc515SConor Walsh# Copyright(c) 2020 Intel Corporation
48bedc515SConor Walsh
58bedc515SConor Walsh"""
68bedc515SConor WalshConfigure an entire Intel DSA instance, using idxd kernel driver, for DPDK use
78bedc515SConor Walsh"""
88bedc515SConor Walsh
98bedc515SConor Walshimport sys
108bedc515SConor Walshimport argparse
118bedc515SConor Walshimport os
128bedc515SConor Walshimport os.path
138bedc515SConor Walsh
148bedc515SConor Walsh
158bedc515SConor Walshclass SysfsDir:
169d8a4375SBruce Richardson    verbose = False
179d8a4375SBruce Richardson
188bedc515SConor Walsh    "Used to read/write paths in a sysfs directory"
198bedc515SConor Walsh    def __init__(self, path):
208bedc515SConor Walsh        self.path = path
218bedc515SConor Walsh
228bedc515SConor Walsh    def read_int(self, filename):
238bedc515SConor Walsh        "Return a value from sysfs file"
249d8a4375SBruce Richardson        if SysfsDir.verbose:
259d8a4375SBruce Richardson            print(f"Reading '{filename}' in {self.path}")
268bedc515SConor Walsh        with open(os.path.join(self.path, filename)) as f:
278bedc515SConor Walsh            return int(f.readline())
288bedc515SConor Walsh
298bedc515SConor Walsh    def write_values(self, values):
308bedc515SConor Walsh        "write dictionary, where key is filename and value is value to write"
318bedc515SConor Walsh        for filename, contents in values.items():
329d8a4375SBruce Richardson            if SysfsDir.verbose:
339d8a4375SBruce Richardson                print(f"Writing '{contents}' to '{filename}' in {self.path}")
348bedc515SConor Walsh            with open(os.path.join(self.path, filename), "w") as f:
358bedc515SConor Walsh                f.write(str(contents))
368bedc515SConor Walsh
378bedc515SConor Walsh
3832776763SBruce Richardsondef get_drv_dir(dtype):
3932776763SBruce Richardson    "Get the sysfs path for the driver, either 'idxd' or 'user'"
4032776763SBruce Richardson    drv_dir = "/sys/bus/dsa/drivers/" + dtype
4132776763SBruce Richardson    if not os.path.exists(drv_dir):
4232776763SBruce Richardson        return "/sys/bus/dsa/drivers/dsa"
4332776763SBruce Richardson    return drv_dir
4432776763SBruce Richardson
4532776763SBruce Richardson
468bedc515SConor Walshdef reset_device(dsa_id):
478bedc515SConor Walsh    "Reset the DSA device and all its queues"
4832776763SBruce Richardson    drv_dir = SysfsDir(get_drv_dir("idxd"))
498bedc515SConor Walsh    drv_dir.write_values({"unbind": f"dsa{dsa_id}"})
508bedc515SConor Walsh
518bedc515SConor Walsh
528bedc515SConor Walshdef get_pci_dir(pci):
538bedc515SConor Walsh    "Search for the sysfs directory of the PCI device"
548bedc515SConor Walsh    base_dir = '/sys/bus/pci/devices/'
558bedc515SConor Walsh    for path, dirs, files in os.walk(base_dir):
568bedc515SConor Walsh        for dir in dirs:
578bedc515SConor Walsh            if pci in dir:
588bedc515SConor Walsh                return os.path.join(base_dir, dir)
598bedc515SConor Walsh    sys.exit(f"Could not find sysfs directory for device {pci}")
608bedc515SConor Walsh
618bedc515SConor Walsh
628bedc515SConor Walshdef get_dsa_id(pci):
638bedc515SConor Walsh    "Get the DSA instance ID using the PCI address of the device"
648bedc515SConor Walsh    pci_dir = get_pci_dir(pci)
658bedc515SConor Walsh    for path, dirs, files in os.walk(pci_dir):
668bedc515SConor Walsh        for dir in dirs:
678bedc515SConor Walsh            if dir.startswith('dsa') and 'wq' not in dir:
688bedc515SConor Walsh                return int(dir[3:])
698bedc515SConor Walsh    sys.exit(f"Could not get device ID for device {pci}")
708bedc515SConor Walsh
718bedc515SConor Walsh
7294b0f04dSKevin Laatzdef parse_wq_opts(wq_opts):
7394b0f04dSKevin Laatz    "Parse user-specified queue configuration, creating a dict of options"
7494b0f04dSKevin Laatz    try:
7594b0f04dSKevin Laatz        return {o.split('=')[0]: o.split('=')[1] for o in wq_opts}
7694b0f04dSKevin Laatz    except ValueError:
7794b0f04dSKevin Laatz        sys.exit("Invalid --wq-option format, use format 'option=value'")
7894b0f04dSKevin Laatz
7994b0f04dSKevin Laatz
8094b0f04dSKevin Laatzdef configure_dsa(dsa_id, args):
818bedc515SConor Walsh    "Configure the DSA instance with appropriate number of queues"
828bedc515SConor Walsh    dsa_dir = SysfsDir(f"/sys/bus/dsa/devices/dsa{dsa_id}")
838bedc515SConor Walsh
848bedc515SConor Walsh    max_groups = dsa_dir.read_int("max_groups")
858bedc515SConor Walsh    max_engines = dsa_dir.read_int("max_engines")
868bedc515SConor Walsh    max_queues = dsa_dir.read_int("max_work_queues")
878bedc515SConor Walsh    max_work_queues_size = dsa_dir.read_int("max_work_queues_size")
888bedc515SConor Walsh
8994b0f04dSKevin Laatz    nb_queues = min(args.q, max_queues)
9094b0f04dSKevin Laatz    if args.q > nb_queues:
918bedc515SConor Walsh        print(f"Setting number of queues to max supported value: {max_queues}")
928bedc515SConor Walsh
938bedc515SConor Walsh    # we want one engine per group, and no more engines than queues
948bedc515SConor Walsh    nb_groups = min(max_engines, max_groups, nb_queues)
958bedc515SConor Walsh    for grp in range(nb_groups):
968bedc515SConor Walsh        dsa_dir.write_values({f"engine{dsa_id}.{grp}/group_id": grp})
978bedc515SConor Walsh
988bedc515SConor Walsh    # configure each queue
998bedc515SConor Walsh    for q in range(nb_queues):
10094b0f04dSKevin Laatz        wqcfg = {"group_id": q % nb_groups,
1018bedc515SConor Walsh                 "type": "user",
1028bedc515SConor Walsh                 "mode": "dedicated",
10394b0f04dSKevin Laatz                 "name": f"{args.prefix}_wq{dsa_id}.{q}",
1048bedc515SConor Walsh                 "priority": 1,
1056a87d036SBruce Richardson                 "max_batch_size": 1024,
10694b0f04dSKevin Laatz                 "size": int(max_work_queues_size / nb_queues)}
10794b0f04dSKevin Laatz        wq_dir = SysfsDir(os.path.join(dsa_dir.path, f"wq{dsa_id}.{q}"))
108*d569af3dSWenwu Ma        if os.path.exists(os.path.join(wq_dir.path, f"driver_name")):
109*d569af3dSWenwu Ma            wqcfg.update({"driver_name": "user"})
110*d569af3dSWenwu Ma        wqcfg.update(parse_wq_opts(args.wq_option))
11194b0f04dSKevin Laatz        wq_dir.write_values(wqcfg)
1128bedc515SConor Walsh
1138bedc515SConor Walsh    # enable device and then queues
11432776763SBruce Richardson    idxd_dir = SysfsDir(get_drv_dir("idxd"))
11532776763SBruce Richardson    idxd_dir.write_values({"bind": f"dsa{dsa_id}"})
11632776763SBruce Richardson
11732776763SBruce Richardson    user_dir = SysfsDir(get_drv_dir("user"))
1188bedc515SConor Walsh    for q in range(nb_queues):
11932776763SBruce Richardson        user_dir.write_values({"bind": f"wq{dsa_id}.{q}"})
1208bedc515SConor Walsh
1218bedc515SConor Walsh
1228bedc515SConor Walshdef main(args):
1238bedc515SConor Walsh    "Main function, does arg parsing and calls config function"
1248bedc515SConor Walsh    arg_p = argparse.ArgumentParser(
1258bedc515SConor Walsh        description="Configure whole DSA device instance for DPDK use")
1268bedc515SConor Walsh    arg_p.add_argument('dsa_id',
1278bedc515SConor Walsh                       help="Specify DSA instance either via DSA instance number or PCI address")
1288bedc515SConor Walsh    arg_p.add_argument('-q', metavar='queues', type=int, default=255,
1298bedc515SConor Walsh                       help="Number of queues to set up")
1308bedc515SConor Walsh    arg_p.add_argument('--name-prefix', metavar='prefix', dest='prefix',
1318bedc515SConor Walsh                       default="dpdk",
1328bedc515SConor Walsh                       help="Prefix for workqueue name to mark for DPDK use [default: 'dpdk']")
1334b918c1aSBruce Richardson    arg_p.add_argument('--wq-option', action='append', default=[],
13494b0f04dSKevin Laatz                       help="Provide additional config option for queues (format 'x=y')")
1359d8a4375SBruce Richardson    arg_p.add_argument('--verbose', '-v', action='store_true',
1369d8a4375SBruce Richardson                       help="Provide addition info on tasks being performed")
1378bedc515SConor Walsh    arg_p.add_argument('--reset', action='store_true',
1388bedc515SConor Walsh                       help="Reset DSA device and its queues")
1398bedc515SConor Walsh    parsed_args = arg_p.parse_args(args[1:])
1408bedc515SConor Walsh
1418bedc515SConor Walsh    dsa_id = parsed_args.dsa_id
1428bedc515SConor Walsh    dsa_id = get_dsa_id(dsa_id) if ':' in dsa_id else dsa_id
1439d8a4375SBruce Richardson
1449d8a4375SBruce Richardson    SysfsDir.verbose = parsed_args.verbose
1458bedc515SConor Walsh    if parsed_args.reset:
1468bedc515SConor Walsh        reset_device(dsa_id)
1478bedc515SConor Walsh    else:
14894b0f04dSKevin Laatz        configure_dsa(dsa_id, parsed_args)
1498bedc515SConor Walsh
1508bedc515SConor Walsh
1518bedc515SConor Walshif __name__ == "__main__":
1528bedc515SConor Walsh    main(sys.argv)
153