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