13f6f8362SLouise Kilheeney#!/usr/bin/env python3 29d7c01f8SBruce Richardson# SPDX-License-Identifier: BSD-3-Clause 39d7c01f8SBruce Richardson# Copyright(c) 2010-2014 Intel Corporation 4c6dab2a8SThomas Monjalon# 5c6dab2a8SThomas Monjalon 6c6dab2a8SThomas Monjalonimport sys 7c6dab2a8SThomas Monjalonimport os 8c6dab2a8SThomas Monjalonimport subprocess 981255f27SStephen Hemmingerimport argparse 107a016af4SYongxin Liuimport platform 1181255f27SStephen Hemminger 12781eafc9SBruce Richardsonfrom glob import glob 131bb98a90SStephen Hemmingerfrom os.path import exists, basename 14781eafc9SBruce Richardsonfrom os.path import join as path_join 15c6dab2a8SThomas Monjalon 168ad08a28SGuduri Prathyusha# The PCI base class for all devices 178ad08a28SGuduri Prathyushanetwork_class = {'Class': '02', 'Vendor': None, 'Device': None, 188ad08a28SGuduri Prathyusha 'SVendor': None, 'SDevice': None} 1907488e29SNicolas Chautruacceleration_class = {'Class': '12', 'Vendor': None, 'Device': None, 2007488e29SNicolas Chautru 'SVendor': None, 'SDevice': None} 21c01c748eSRosen Xuifpga_class = {'Class': '12', 'Vendor': '8086', 'Device': '0b30', 22c01c748eSRosen Xu 'SVendor': None, 'SDevice': None} 238ad08a28SGuduri Prathyushaencryption_class = {'Class': '10', 'Vendor': None, 'Device': None, 248ad08a28SGuduri Prathyusha 'SVendor': None, 'SDevice': None} 258ad08a28SGuduri Prathyushaintel_processor_class = {'Class': '0b', 'Vendor': '8086', 'Device': None, 268ad08a28SGuduri Prathyusha 'SVendor': None, 'SDevice': None} 2732a02dbfSGuduri Prathyushacavium_sso = {'Class': '08', 'Vendor': '177d', 'Device': 'a04b,a04d', 2832a02dbfSGuduri Prathyusha 'SVendor': None, 'SDevice': None} 2980a1858dSGuduri Prathyushacavium_fpa = {'Class': '08', 'Vendor': '177d', 'Device': 'a053', 3080a1858dSGuduri Prathyusha 'SVendor': None, 'SDevice': None} 31156c42eaSJerin Jacobcavium_pkx = {'Class': '08', 'Vendor': '177d', 'Device': 'a0dd,a049', 32156c42eaSJerin Jacob 'SVendor': None, 'SDevice': None} 33f4bc0010SPavan Nikhileshcavium_tim = {'Class': '08', 'Vendor': '177d', 'Device': 'a051', 34f4bc0010SPavan Nikhilesh 'SVendor': None, 'SDevice': None} 359d35895eSSunila Sahucavium_zip = {'Class': '12', 'Vendor': '177d', 'Device': 'a037', 369d35895eSSunila Sahu 'SVendor': None, 'SDevice': None} 3720526313SXiaohua Zhangavp_vnic = {'Class': '05', 'Vendor': '1af4', 'Device': '1110', 3820526313SXiaohua Zhang 'SVendor': None, 'SDevice': None} 398ad08a28SGuduri Prathyusha 4024d9c5d5STomasz Duszynskicnxk_bphy = {'Class': '08', 'Vendor': '177d', 'Device': 'a089', 4124d9c5d5STomasz Duszynski 'SVendor': None, 'SDevice': None} 423d27e49eSTomasz Duszynskicnxk_bphy_cgx = {'Class': '08', 'Vendor': '177d', 'Device': 'a059,a060', 433d27e49eSTomasz Duszynski 'SVendor': None, 'SDevice': None} 442ff80151SRadha Mohan Chintakuntlacnxk_dma = {'Class': '08', 'Vendor': '177d', 'Device': 'a081', 452ff80151SRadha Mohan Chintakuntla 'SVendor': None, 'SDevice': None} 4669daa9e5SNithin Dabilpuramcnxk_inl_dev = {'Class': '08', 'Vendor': '177d', 'Device': 'a0f0,a0f1', 4769daa9e5SNithin Dabilpuram 'SVendor': None, 'SDevice': None} 480bcc6644SJerin Jacob 49fb73eb2fSChengwen Fenghisilicon_dma = {'Class': '08', 'Vendor': '19e5', 'Device': 'a122', 50fb73eb2fSChengwen Feng 'SVendor': None, 'SDevice': None} 511bbc35a8SAnoob Josephodm_dma = {'Class': '08', 'Vendor': '177d', 'Device': 'a08c', 521bbc35a8SAnoob Joseph 'SVendor': None, 'SDevice': None} 53fb73eb2fSChengwen Feng 54240078c0STimothy McDanielintel_dlb = {'Class': '0b', 'Vendor': '8086', 'Device': '270b,2710,2714', 55240078c0STimothy McDaniel 'SVendor': None, 'SDevice': None} 56c358ba7aSStephen Hemmingerintel_ioat_bdw = {'Class': '08', 'Vendor': '8086', 57c358ba7aSStephen Hemminger 'Device': '6f20,6f21,6f22,6f23,6f24,6f25,6f26,6f27,6f2e,6f2f', 5812d4777aSBruce Richardson 'SVendor': None, 'SDevice': None} 5912d4777aSBruce Richardsonintel_ioat_skx = {'Class': '08', 'Vendor': '8086', 'Device': '2021', 6012d4777aSBruce Richardson 'SVendor': None, 'SDevice': None} 61299e282fSRadu Nicolauintel_ioat_icx = {'Class': '08', 'Vendor': '8086', 'Device': '0b00', 62299e282fSRadu Nicolau 'SVendor': None, 'SDevice': None} 6343f9b521SKevin Laatzintel_idxd_spr = {'Class': '08', 'Vendor': '8086', 'Device': '0b25', 6443f9b521SKevin Laatz 'SVendor': None, 'SDevice': None} 65034c328eSXiaoyun Liintel_ntb_skx = {'Class': '06', 'Vendor': '8086', 'Device': '201c', 66034c328eSXiaoyun Li 'SVendor': None, 'SDevice': None} 67f5057be3SXiaoyun Liintel_ntb_icx = {'Class': '06', 'Vendor': '8086', 'Device': '347e', 68f5057be3SXiaoyun Li 'SVendor': None, 'SDevice': None} 6912d4777aSBruce Richardson 7033e71acfSJerin Jacobcnxk_sso = {'Class': '08', 'Vendor': '177d', 'Device': 'a0f9,a0fa', 712ff80151SRadha Mohan Chintakuntla 'SVendor': None, 'SDevice': None} 7233e71acfSJerin Jacobcnxk_npa = {'Class': '08', 'Vendor': '177d', 'Device': 'a0fb,a0fc', 732ff80151SRadha Mohan Chintakuntla 'SVendor': None, 'SDevice': None} 7433e71acfSJerin Jacobcn9k_ree = {'Class': '08', 'Vendor': '177d', 'Device': 'a0f4', 752ff80151SRadha Mohan Chintakuntla 'SVendor': None, 'SDevice': None} 762ff80151SRadha Mohan Chintakuntla 771216ac76SAndy Peivirtio_blk = {'Class': '01', 'Vendor': "1af4", 'Device': '1001,1042', 781216ac76SAndy Pei 'SVendor': None, 'SDevice': None} 791216ac76SAndy Pei 80b9aaa675SSrikanth Yalavarthicnxk_ml = {'Class': '08', 'Vendor': '177d', 'Device': 'a092', 81b9aaa675SSrikanth Yalavarthi 'SVendor': None, 'SDevice': None} 82b9aaa675SSrikanth Yalavarthi 83c01c748eSRosen Xunetwork_devices = [network_class, cavium_pkx, avp_vnic, ifpga_class] 8407488e29SNicolas Chautrubaseband_devices = [acceleration_class] 858ad08a28SGuduri Prathyushacrypto_devices = [encryption_class, intel_processor_class] 862ff80151SRadha Mohan Chintakuntladma_devices = [cnxk_dma, hisilicon_dma, 871bbc35a8SAnoob Joseph intel_idxd_spr, intel_ioat_bdw, intel_ioat_icx, intel_ioat_skx, 881bbc35a8SAnoob Joseph odm_dma] 8933e71acfSJerin Jacobeventdev_devices = [cavium_sso, cavium_tim, intel_dlb, cnxk_sso] 9033e71acfSJerin Jacobmempool_devices = [cavium_fpa, cnxk_npa] 919d35895eSSunila Sahucompress_devices = [cavium_zip] 9233e71acfSJerin Jacobregex_devices = [cn9k_ree] 93b9aaa675SSrikanth Yalavarthiml_devices = [cnxk_ml] 942ff80151SRadha Mohan Chintakuntlamisc_devices = [cnxk_bphy, cnxk_bphy_cgx, cnxk_inl_dev, 951216ac76SAndy Pei intel_ntb_skx, intel_ntb_icx, 961216ac76SAndy Pei virtio_blk] 97c6dab2a8SThomas Monjalon 98c6dab2a8SThomas Monjalon# global dict ethernet devices present. Dictionary indexed by PCI address. 99c6dab2a8SThomas Monjalon# Each device within this is itself a dictionary of device properties 100c6dab2a8SThomas Monjalondevices = {} 101c6dab2a8SThomas Monjalon# list of supported DPDK drivers 102c6dab2a8SThomas Monjalondpdk_drivers = ["igb_uio", "vfio-pci", "uio_pci_generic"] 103681a6728SAnatoly Burakov# list of currently loaded kernel modules 104681a6728SAnatoly Burakovloaded_modules = None 105c6dab2a8SThomas Monjalon 106c6dab2a8SThomas Monjalon# command-line arg flags 107c6dab2a8SThomas Monjalonb_flag = None 108c6dab2a8SThomas Monjalonstatus_flag = False 109c6dab2a8SThomas Monjalonforce_flag = False 1106ca0f1c8SFidaullah Noonarinoiommu_flag = False 111c6dab2a8SThomas Monjalonargs = [] 112c6dab2a8SThomas Monjalon 11362d3ce60SStephen Hemminger 114681a6728SAnatoly Burakov# check if a specific kernel module is loaded 115681a6728SAnatoly Burakovdef module_is_loaded(module): 116681a6728SAnatoly Burakov global loaded_modules 117681a6728SAnatoly Burakov 11843623124SPavan Nikhilesh if module == 'vfio_pci': 11943623124SPavan Nikhilesh module = 'vfio-pci' 12043623124SPavan Nikhilesh 121681a6728SAnatoly Burakov if loaded_modules: 122681a6728SAnatoly Burakov return module in loaded_modules 123681a6728SAnatoly Burakov 124681a6728SAnatoly Burakov # Get list of sysfs modules (both built-in and dynamically loaded) 125681a6728SAnatoly Burakov sysfs_path = '/sys/module/' 126681a6728SAnatoly Burakov 127681a6728SAnatoly Burakov # Get the list of directories in sysfs_path 128681a6728SAnatoly Burakov sysfs_mods = [m for m in os.listdir(sysfs_path) 129681a6728SAnatoly Burakov if os.path.isdir(os.path.join(sysfs_path, m))] 130681a6728SAnatoly Burakov 131681a6728SAnatoly Burakov # special case for vfio_pci (module is named vfio-pci, 132681a6728SAnatoly Burakov # but its .ko is named vfio_pci) 133681a6728SAnatoly Burakov sysfs_mods = [a if a != 'vfio_pci' else 'vfio-pci' for a in sysfs_mods] 134681a6728SAnatoly Burakov 135681a6728SAnatoly Burakov loaded_modules = sysfs_mods 136681a6728SAnatoly Burakov 1377a016af4SYongxin Liu # add built-in modules as loaded 1387a016af4SYongxin Liu release = platform.uname().release 1397a016af4SYongxin Liu filename = os.path.join("/lib/modules/", release, "modules.builtin") 1407a016af4SYongxin Liu if os.path.exists(filename): 1417a016af4SYongxin Liu try: 1427a016af4SYongxin Liu with open(filename) as f: 1437a016af4SYongxin Liu loaded_modules += [os.path.splitext(os.path.basename(mod))[0] for mod in f] 1447a016af4SYongxin Liu except IOError: 1457a016af4SYongxin Liu print("Warning: cannot read list of built-in kernel modules") 1467a016af4SYongxin Liu 1477a016af4SYongxin Liu return module in loaded_modules 148681a6728SAnatoly Burakov 149c6dab2a8SThomas Monjalon 150c6dab2a8SThomas Monjalondef check_modules(): 151c6dab2a8SThomas Monjalon '''Checks that igb_uio is loaded''' 152c6dab2a8SThomas Monjalon global dpdk_drivers 153c6dab2a8SThomas Monjalon 154c6dab2a8SThomas Monjalon # list of supported modules 155c6dab2a8SThomas Monjalon mods = [{"Name": driver, "Found": False} for driver in dpdk_drivers] 156c6dab2a8SThomas Monjalon 157c6dab2a8SThomas Monjalon # first check if module is loaded 158c6dab2a8SThomas Monjalon for mod in mods: 159681a6728SAnatoly Burakov if module_is_loaded(mod["Name"]): 160c6dab2a8SThomas Monjalon mod["Found"] = True 161c6dab2a8SThomas Monjalon 162c6dab2a8SThomas Monjalon # check if we have at least one loaded module 163c6dab2a8SThomas Monjalon if True not in [mod["Found"] for mod in mods] and b_flag is not None: 1642804529fSAnatoly Burakov print("Warning: no supported DPDK kernel modules are loaded", file=sys.stderr) 165c6dab2a8SThomas Monjalon 166c6dab2a8SThomas Monjalon # change DPDK driver list to only contain drivers that are loaded 167c6dab2a8SThomas Monjalon dpdk_drivers = [mod["Name"] for mod in mods if mod["Found"]] 168c6dab2a8SThomas Monjalon 169c6dab2a8SThomas Monjalon 170c6dab2a8SThomas Monjalondef has_driver(dev_id): 171c6dab2a8SThomas Monjalon '''return true if a device is assigned to a driver. False otherwise''' 172c6dab2a8SThomas Monjalon return "Driver_str" in devices[dev_id] 173c6dab2a8SThomas Monjalon 174c6dab2a8SThomas Monjalon 175c3ce205dSGuduri Prathyushadef get_pci_device_details(dev_id, probe_lspci): 176c6dab2a8SThomas Monjalon '''This function gets additional details for a PCI device''' 177c6dab2a8SThomas Monjalon device = {} 178c6dab2a8SThomas Monjalon 179c3ce205dSGuduri Prathyusha if probe_lspci: 1803f6f8362SLouise Kilheeney extra_info = subprocess.check_output(["lspci", "-vmmks", dev_id]).splitlines() 181c6dab2a8SThomas Monjalon # parse lspci details 182c6dab2a8SThomas Monjalon for line in extra_info: 183d58360c6SStephen Hemminger if not line: 184c6dab2a8SThomas Monjalon continue 18508ab6cd3SChristos Ricudis name, value = line.decode("utf8").split("\t", 1) 186c6dab2a8SThomas Monjalon name = name.strip(":") + "_str" 187c6dab2a8SThomas Monjalon device[name] = value 188c6dab2a8SThomas Monjalon # check for a unix interface name 189c6dab2a8SThomas Monjalon device["Interface"] = "" 190c6dab2a8SThomas Monjalon for base, dirs, _ in os.walk("/sys/bus/pci/devices/%s/" % dev_id): 191c6dab2a8SThomas Monjalon if "net" in dirs: 192c6dab2a8SThomas Monjalon device["Interface"] = \ 193c6dab2a8SThomas Monjalon ",".join(os.listdir(os.path.join(base, "net"))) 194c6dab2a8SThomas Monjalon break 195c6dab2a8SThomas Monjalon # check if a port is used for ssh connection 196c6dab2a8SThomas Monjalon device["Ssh_if"] = False 197c6dab2a8SThomas Monjalon device["Active"] = "" 198c6dab2a8SThomas Monjalon 199c6dab2a8SThomas Monjalon return device 200c6dab2a8SThomas Monjalon 20162d3ce60SStephen Hemminger 202ea9f00f7SGuduri Prathyushadef clear_data(): 203ea9f00f7SGuduri Prathyusha '''This function clears any old data''' 20493b93bebSTimothy Redaelli global devices 205ea9f00f7SGuduri Prathyusha devices = {} 206c6dab2a8SThomas Monjalon 20762d3ce60SStephen Hemminger 208ea9f00f7SGuduri Prathyushadef get_device_details(devices_type): 209c6dab2a8SThomas Monjalon '''This function populates the "devices" dictionary. The keys used are 210c6dab2a8SThomas Monjalon the pci addresses (domain:bus:slot.func). The values are themselves 211c6dab2a8SThomas Monjalon dictionaries - one for each NIC.''' 212c6dab2a8SThomas Monjalon global devices 213c6dab2a8SThomas Monjalon global dpdk_drivers 214c6dab2a8SThomas Monjalon 215c6dab2a8SThomas Monjalon # first loop through and read details for all devices 216c3ce205dSGuduri Prathyusha # request machine readable format, with numeric IDs and String 217c6dab2a8SThomas Monjalon dev = {} 2183f6f8362SLouise Kilheeney dev_lines = subprocess.check_output(["lspci", "-Dvmmnnk"]).splitlines() 219c6dab2a8SThomas Monjalon for dev_line in dev_lines: 220d58360c6SStephen Hemminger if not dev_line: 2218ad08a28SGuduri Prathyusha if device_type_match(dev, devices_type): 2228ad08a28SGuduri Prathyusha # Replace "Driver" with "Driver_str" to have consistency of 2238ad08a28SGuduri Prathyusha # of dictionary key names 224c3ce205dSGuduri Prathyusha if "Driver" in dev.keys(): 225c3ce205dSGuduri Prathyusha dev["Driver_str"] = dev.pop("Driver") 226c76a10ecSAnatoly Burakov if "Module" in dev.keys(): 227c76a10ecSAnatoly Burakov dev["Module_str"] = dev.pop("Module") 228c6dab2a8SThomas Monjalon # use dict to make copy of dev 229c6dab2a8SThomas Monjalon devices[dev["Slot"]] = dict(dev) 230c3ce205dSGuduri Prathyusha # Clear previous device's data 231c3ce205dSGuduri Prathyusha dev = {} 232c6dab2a8SThomas Monjalon else: 23308ab6cd3SChristos Ricudis name, value = dev_line.decode("utf8").split("\t", 1) 234c3ce205dSGuduri Prathyusha value_list = value.rsplit(' ', 1) 235d58360c6SStephen Hemminger if value_list: 236c3ce205dSGuduri Prathyusha # String stored in <name>_str 237c3ce205dSGuduri Prathyusha dev[name.rstrip(":") + '_str'] = value_list[0] 238c3ce205dSGuduri Prathyusha # Numeric IDs 239c3ce205dSGuduri Prathyusha dev[name.rstrip(":")] = value_list[len(value_list) - 1] \ 240c3ce205dSGuduri Prathyusha .rstrip("]").lstrip("[") 241c6dab2a8SThomas Monjalon 2428ad08a28SGuduri Prathyusha if devices_type == network_devices: 243c6dab2a8SThomas Monjalon # check what is the interface if any for an ssh connection if 244c6dab2a8SThomas Monjalon # any to this host, so we can mark it later. 245c6dab2a8SThomas Monjalon ssh_if = [] 2463f6f8362SLouise Kilheeney route = subprocess.check_output(["ip", "-o", "route"]) 247c6dab2a8SThomas Monjalon # filter out all lines for 169.254 routes 248c6dab2a8SThomas Monjalon route = "\n".join(filter(lambda ln: not ln.startswith("169.254"), 249c6dab2a8SThomas Monjalon route.decode().splitlines())) 250c6dab2a8SThomas Monjalon rt_info = route.split() 251c6dab2a8SThomas Monjalon for i in range(len(rt_info) - 1): 252c6dab2a8SThomas Monjalon if rt_info[i] == "dev": 253c6dab2a8SThomas Monjalon ssh_if.append(rt_info[i + 1]) 254c6dab2a8SThomas Monjalon 255c6dab2a8SThomas Monjalon # based on the basic info, get extended text details 256c6dab2a8SThomas Monjalon for d in devices.keys(): 2578ad08a28SGuduri Prathyusha if not device_type_match(devices[d], devices_type): 258617d9052SYoni Gilad continue 259617d9052SYoni Gilad 260c6dab2a8SThomas Monjalon # get additional info and add it to existing data 261c6dab2a8SThomas Monjalon devices[d] = devices[d].copy() 262c3ce205dSGuduri Prathyusha # No need to probe lspci 263c3ce205dSGuduri Prathyusha devices[d].update(get_pci_device_details(d, False).items()) 264c6dab2a8SThomas Monjalon 2658ad08a28SGuduri Prathyusha if devices_type == network_devices: 266ea9f00f7SGuduri Prathyusha for _if in ssh_if: 267ea9f00f7SGuduri Prathyusha if _if in devices[d]["Interface"].split(","): 268ea9f00f7SGuduri Prathyusha devices[d]["Ssh_if"] = True 269ea9f00f7SGuduri Prathyusha devices[d]["Active"] = "*Active*" 270ea9f00f7SGuduri Prathyusha break 271ea9f00f7SGuduri Prathyusha 272c6dab2a8SThomas Monjalon # add igb_uio to list of supporting modules if needed 273c6dab2a8SThomas Monjalon if "Module_str" in devices[d]: 274c6dab2a8SThomas Monjalon for driver in dpdk_drivers: 275c6dab2a8SThomas Monjalon if driver not in devices[d]["Module_str"]: 276c6dab2a8SThomas Monjalon devices[d]["Module_str"] = \ 277c6dab2a8SThomas Monjalon devices[d]["Module_str"] + ",%s" % driver 278c6dab2a8SThomas Monjalon else: 279c6dab2a8SThomas Monjalon devices[d]["Module_str"] = ",".join(dpdk_drivers) 280c6dab2a8SThomas Monjalon 281c6dab2a8SThomas Monjalon # make sure the driver and module strings do not have any duplicates 282c6dab2a8SThomas Monjalon if has_driver(d): 283c6dab2a8SThomas Monjalon modules = devices[d]["Module_str"].split(",") 284c6dab2a8SThomas Monjalon if devices[d]["Driver_str"] in modules: 285c6dab2a8SThomas Monjalon modules.remove(devices[d]["Driver_str"]) 286c6dab2a8SThomas Monjalon devices[d]["Module_str"] = ",".join(modules) 287c6dab2a8SThomas Monjalon 288c6dab2a8SThomas Monjalon 2898ad08a28SGuduri Prathyushadef device_type_match(dev, devices_type): 2908ad08a28SGuduri Prathyusha for i in range(len(devices_type)): 2918ad08a28SGuduri Prathyusha param_count = len( 2928ad08a28SGuduri Prathyusha [x for x in devices_type[i].values() if x is not None]) 2938ad08a28SGuduri Prathyusha match_count = 0 2948ad08a28SGuduri Prathyusha if dev["Class"][0:2] == devices_type[i]["Class"]: 2958ad08a28SGuduri Prathyusha match_count = match_count + 1 2968ad08a28SGuduri Prathyusha for key in devices_type[i].keys(): 2978ad08a28SGuduri Prathyusha if key != 'Class' and devices_type[i][key]: 2988ad08a28SGuduri Prathyusha value_list = devices_type[i][key].split(',') 2998ad08a28SGuduri Prathyusha for value in value_list: 3008ad08a28SGuduri Prathyusha if value.strip(' ') == dev[key]: 3018ad08a28SGuduri Prathyusha match_count = match_count + 1 3028ad08a28SGuduri Prathyusha # count must be the number of non None parameters to match 3038ad08a28SGuduri Prathyusha if match_count == param_count: 3048ad08a28SGuduri Prathyusha return True 3058ad08a28SGuduri Prathyusha return False 3068ad08a28SGuduri Prathyusha 30762d3ce60SStephen Hemminger 308c6dab2a8SThomas Monjalondef dev_id_from_dev_name(dev_name): 309c6dab2a8SThomas Monjalon '''Take a device "name" - a string passed in by user to identify a NIC 310c6dab2a8SThomas Monjalon device, and determine the device id - i.e. the domain:bus:slot.func - for 311c6dab2a8SThomas Monjalon it, which can then be used to index into the devices array''' 312c6dab2a8SThomas Monjalon 313c6dab2a8SThomas Monjalon # check if it's already a suitable index 314c6dab2a8SThomas Monjalon if dev_name in devices: 315c6dab2a8SThomas Monjalon return dev_name 316c6dab2a8SThomas Monjalon # check if it's an index just missing the domain part 317b5685e39SStephen Hemminger if "0000:" + dev_name in devices: 318c6dab2a8SThomas Monjalon return "0000:" + dev_name 319b5685e39SStephen Hemminger 320c6dab2a8SThomas Monjalon # check if it's an interface name, e.g. eth1 321c6dab2a8SThomas Monjalon for d in devices.keys(): 322c6dab2a8SThomas Monjalon if dev_name in devices[d]["Interface"].split(","): 323c6dab2a8SThomas Monjalon return devices[d]["Slot"] 324c6dab2a8SThomas Monjalon # if nothing else matches - error 32515f6aac7SAnatoly Burakov raise ValueError("Unknown device: %s. " 326c6dab2a8SThomas Monjalon "Please specify device in \"bus:slot.func\" format" % dev_name) 327c6dab2a8SThomas Monjalon 328c6dab2a8SThomas Monjalon 329c6dab2a8SThomas Monjalondef unbind_one(dev_id, force): 330c6dab2a8SThomas Monjalon '''Unbind the device identified by "dev_id" from its current driver''' 331c6dab2a8SThomas Monjalon dev = devices[dev_id] 332c6dab2a8SThomas Monjalon if not has_driver(dev_id): 3332804529fSAnatoly Burakov print("Notice: %s %s %s is not currently managed by any driver" % 3342804529fSAnatoly Burakov (dev["Slot"], dev["Device_str"], dev["Interface"]), file=sys.stderr) 335c6dab2a8SThomas Monjalon return 336c6dab2a8SThomas Monjalon 337c6dab2a8SThomas Monjalon # prevent us disconnecting ourselves 338c6dab2a8SThomas Monjalon if dev["Ssh_if"] and not force: 3392804529fSAnatoly Burakov print("Warning: routing table indicates that interface %s is active. " 3402804529fSAnatoly Burakov "Skipping unbind" % dev_id, file=sys.stderr) 341c6dab2a8SThomas Monjalon return 342c6dab2a8SThomas Monjalon 343c6dab2a8SThomas Monjalon # write to /sys to unbind 344c6dab2a8SThomas Monjalon filename = "/sys/bus/pci/drivers/%s/unbind" % dev["Driver_str"] 345c6dab2a8SThomas Monjalon try: 346c6dab2a8SThomas Monjalon f = open(filename, "a") 34762d3ce60SStephen Hemminger except OSError as err: 34862d3ce60SStephen Hemminger sys.exit("Error: unbind failed for %s - Cannot open %s: %s" % 34962d3ce60SStephen Hemminger (dev_id, filename, err)) 350c6dab2a8SThomas Monjalon f.write(dev_id) 351c6dab2a8SThomas Monjalon f.close() 352c6dab2a8SThomas Monjalon 353c6dab2a8SThomas Monjalon 354c6dab2a8SThomas Monjalondef bind_one(dev_id, driver, force): 355c6dab2a8SThomas Monjalon '''Bind the device given by "dev_id" to the driver "driver". If the device 356c6dab2a8SThomas Monjalon is already bound to a different driver, it will be unbound first''' 357c6dab2a8SThomas Monjalon dev = devices[dev_id] 358c6dab2a8SThomas Monjalon saved_driver = None # used to rollback any unbind in case of failure 359c6dab2a8SThomas Monjalon 360c6dab2a8SThomas Monjalon # prevent disconnection of our ssh session 361c6dab2a8SThomas Monjalon if dev["Ssh_if"] and not force: 3622804529fSAnatoly Burakov print("Warning: routing table indicates that interface %s is active. " 3632804529fSAnatoly Burakov "Not modifying" % dev_id, file=sys.stderr) 364c6dab2a8SThomas Monjalon return 365c6dab2a8SThomas Monjalon 366c6dab2a8SThomas Monjalon # unbind any existing drivers we don't want 367c6dab2a8SThomas Monjalon if has_driver(dev_id): 368c6dab2a8SThomas Monjalon if dev["Driver_str"] == driver: 3692804529fSAnatoly Burakov print("Notice: %s already bound to driver %s, skipping" % 3702804529fSAnatoly Burakov (dev_id, driver), file=sys.stderr) 371c6dab2a8SThomas Monjalon return 372c6dab2a8SThomas Monjalon saved_driver = dev["Driver_str"] 373c6dab2a8SThomas Monjalon unbind_one(dev_id, force) 374c6dab2a8SThomas Monjalon dev["Driver_str"] = "" # clear driver string 375c6dab2a8SThomas Monjalon 3762fc35029SGuduri Prathyusha # For kernels >= 3.15 driver_override can be used to specify the driver 3772fc35029SGuduri Prathyusha # for a device rather than relying on the driver to provide a positive 3782fc35029SGuduri Prathyusha # match of the device. The existing process of looking up 3792fc35029SGuduri Prathyusha # the vendor and device ID, adding them to the driver new_id, 3802fc35029SGuduri Prathyusha # will erroneously bind other devices too which has the additional burden 3812fc35029SGuduri Prathyusha # of unbinding those devices 382c6dab2a8SThomas Monjalon if driver in dpdk_drivers: 3832fc35029SGuduri Prathyusha filename = "/sys/bus/pci/devices/%s/driver_override" % dev_id 3841bb98a90SStephen Hemminger if exists(filename): 3852fc35029SGuduri Prathyusha try: 3862fc35029SGuduri Prathyusha f = open(filename, "w") 38762d3ce60SStephen Hemminger except OSError as err: 38862d3ce60SStephen Hemminger print("Error: bind failed for %s - Cannot open %s: %s" 38962d3ce60SStephen Hemminger % (dev_id, filename, err), file=sys.stderr) 3902fc35029SGuduri Prathyusha return 3912fc35029SGuduri Prathyusha try: 3922fc35029SGuduri Prathyusha f.write("%s" % driver) 3932fc35029SGuduri Prathyusha f.close() 39462d3ce60SStephen Hemminger except OSError as err: 3952fc35029SGuduri Prathyusha print("Error: bind failed for %s - Cannot write driver %s to " 39662d3ce60SStephen Hemminger "PCI ID: %s" % (dev_id, driver, err), file=sys.stderr) 3972fc35029SGuduri Prathyusha return 3982fc35029SGuduri Prathyusha # For kernels < 3.15 use new_id to add PCI id's to the driver 3992fc35029SGuduri Prathyusha else: 400c6dab2a8SThomas Monjalon filename = "/sys/bus/pci/drivers/%s/new_id" % driver 401c6dab2a8SThomas Monjalon try: 402c6dab2a8SThomas Monjalon f = open(filename, "w") 40362d3ce60SStephen Hemminger except OSError as err: 40462d3ce60SStephen Hemminger print("Error: bind failed for %s - Cannot open %s: %s" 40562d3ce60SStephen Hemminger % (dev_id, filename, err), file=sys.stderr) 406c6dab2a8SThomas Monjalon return 407c6dab2a8SThomas Monjalon try: 4088ad08a28SGuduri Prathyusha # Convert Device and Vendor Id to int to write to new_id 4098ad08a28SGuduri Prathyusha f.write("%04x %04x" % (int(dev["Vendor"], 16), 4108ad08a28SGuduri Prathyusha int(dev["Device"], 16))) 411c6dab2a8SThomas Monjalon f.close() 41262d3ce60SStephen Hemminger except OSError as err: 413c6dab2a8SThomas Monjalon print("Error: bind failed for %s - Cannot write new PCI ID to " 41462d3ce60SStephen Hemminger "driver %s: %s" % (dev_id, driver, err), file=sys.stderr) 415c6dab2a8SThomas Monjalon return 416c6dab2a8SThomas Monjalon 417c6dab2a8SThomas Monjalon # do the bind by writing to /sys 418c6dab2a8SThomas Monjalon filename = "/sys/bus/pci/drivers/%s/bind" % driver 419c6dab2a8SThomas Monjalon try: 420c6dab2a8SThomas Monjalon f = open(filename, "a") 42162d3ce60SStephen Hemminger except OSError as err: 42262d3ce60SStephen Hemminger print("Error: bind failed for %s - Cannot open %s: %s" 42362d3ce60SStephen Hemminger % (dev_id, filename, err), file=sys.stderr) 424c6dab2a8SThomas Monjalon if saved_driver is not None: # restore any previous driver 425c6dab2a8SThomas Monjalon bind_one(dev_id, saved_driver, force) 426c6dab2a8SThomas Monjalon return 427c6dab2a8SThomas Monjalon try: 428c6dab2a8SThomas Monjalon f.write(dev_id) 429c6dab2a8SThomas Monjalon f.close() 43062d3ce60SStephen Hemminger except OSError as err: 431c6dab2a8SThomas Monjalon # for some reason, closing dev_id after adding a new PCI ID to new_id 432c6dab2a8SThomas Monjalon # results in IOError. however, if the device was successfully bound, 433c6dab2a8SThomas Monjalon # we don't care for any errors and can safely ignore IOError 434c3ce205dSGuduri Prathyusha tmp = get_pci_device_details(dev_id, True) 435c6dab2a8SThomas Monjalon if "Driver_str" in tmp and tmp["Driver_str"] == driver: 436c6dab2a8SThomas Monjalon return 43762d3ce60SStephen Hemminger print("Error: bind failed for %s - Cannot bind to driver %s: %s" 43862d3ce60SStephen Hemminger % (dev_id, driver, err), file=sys.stderr) 439c6dab2a8SThomas Monjalon if saved_driver is not None: # restore any previous driver 440c6dab2a8SThomas Monjalon bind_one(dev_id, saved_driver, force) 441c6dab2a8SThomas Monjalon return 442c6dab2a8SThomas Monjalon 443720b7a05SGuduri Prathyusha # For kernels > 3.15 driver_override is used to bind a device to a driver. 444720b7a05SGuduri Prathyusha # Before unbinding it, overwrite driver_override with empty string so that 445720b7a05SGuduri Prathyusha # the device can be bound to any other driver 446720b7a05SGuduri Prathyusha filename = "/sys/bus/pci/devices/%s/driver_override" % dev_id 4471bb98a90SStephen Hemminger if exists(filename): 448720b7a05SGuduri Prathyusha try: 449720b7a05SGuduri Prathyusha f = open(filename, "w") 45062d3ce60SStephen Hemminger except OSError as err: 45162d3ce60SStephen Hemminger sys.exit("Error: unbind failed for %s - Cannot open %s: %s" 45262d3ce60SStephen Hemminger % (dev_id, filename, err)) 453720b7a05SGuduri Prathyusha try: 454720b7a05SGuduri Prathyusha f.write("\00") 455720b7a05SGuduri Prathyusha f.close() 45662d3ce60SStephen Hemminger except OSError as err: 45762d3ce60SStephen Hemminger sys.exit("Error: unbind failed for %s - Cannot write %s: %s" 45862d3ce60SStephen Hemminger % (dev_id, filename, err)) 459720b7a05SGuduri Prathyusha 460c6dab2a8SThomas Monjalon 461c6dab2a8SThomas Monjalondef unbind_all(dev_list, force=False): 462c6dab2a8SThomas Monjalon """Unbind method, takes a list of device locations""" 463657c7133SFerruh Yigit 464657c7133SFerruh Yigit if dev_list[0] == "dpdk": 465657c7133SFerruh Yigit for d in devices.keys(): 466657c7133SFerruh Yigit if "Driver_str" in devices[d]: 467657c7133SFerruh Yigit if devices[d]["Driver_str"] in dpdk_drivers: 468657c7133SFerruh Yigit unbind_one(devices[d]["Slot"], force) 469657c7133SFerruh Yigit return 470657c7133SFerruh Yigit 47115f6aac7SAnatoly Burakov try: 472c6dab2a8SThomas Monjalon dev_list = map(dev_id_from_dev_name, dev_list) 47315f6aac7SAnatoly Burakov except ValueError as ex: 47415f6aac7SAnatoly Burakov print(ex) 47515f6aac7SAnatoly Burakov sys.exit(1) 47615f6aac7SAnatoly Burakov 477c6dab2a8SThomas Monjalon for d in dev_list: 478c6dab2a8SThomas Monjalon unbind_one(d, force) 479c6dab2a8SThomas Monjalon 480c6dab2a8SThomas Monjalon 4816ca0f1c8SFidaullah Noonaridef has_iommu(): 4826ca0f1c8SFidaullah Noonari """Check if IOMMU is enabled on system""" 4836ca0f1c8SFidaullah Noonari return len(os.listdir("/sys/class/iommu")) > 0 4846ca0f1c8SFidaullah Noonari 4856ca0f1c8SFidaullah Noonari 4866ca0f1c8SFidaullah Noonaridef check_noiommu_mode(): 4876ca0f1c8SFidaullah Noonari """Check and enable the noiommu mode for VFIO drivers""" 4886ca0f1c8SFidaullah Noonari global noiommu_flag 4896ca0f1c8SFidaullah Noonari filename = "/sys/module/vfio/parameters/enable_unsafe_noiommu_mode" 4906ca0f1c8SFidaullah Noonari 4916ca0f1c8SFidaullah Noonari try: 4926ca0f1c8SFidaullah Noonari with open(filename, "r") as f: 493c77887adSRogelio Domínguez Hernández value = f.read(1) 494c77887adSRogelio Domínguez Hernández if value in ("1", "y" ,"Y"): 4956ca0f1c8SFidaullah Noonari return 4966ca0f1c8SFidaullah Noonari except OSError as err: 4976ca0f1c8SFidaullah Noonari sys.exit(f"Error: failed to check unsafe noiommu mode - Cannot open {filename}: {err}") 4986ca0f1c8SFidaullah Noonari 4996ca0f1c8SFidaullah Noonari if not noiommu_flag: 5006ca0f1c8SFidaullah Noonari sys.exit("Error: IOMMU support is disabled, use --noiommu-mode for binding in noiommu mode") 5016ca0f1c8SFidaullah Noonari 5026ca0f1c8SFidaullah Noonari try: 5036ca0f1c8SFidaullah Noonari with open(filename, "w") as f: 5046ca0f1c8SFidaullah Noonari f.write("1") 5056ca0f1c8SFidaullah Noonari except OSError as err: 5066ca0f1c8SFidaullah Noonari sys.exit(f"Error: failed to enable unsafe noiommu mode - Cannot open {filename}: {err}") 5076ca0f1c8SFidaullah Noonari print("Warning: enabling unsafe no IOMMU mode for VFIO drivers") 5086ca0f1c8SFidaullah Noonari 5096ca0f1c8SFidaullah Noonari 510c6dab2a8SThomas Monjalondef bind_all(dev_list, driver, force=False): 511c6dab2a8SThomas Monjalon """Bind method, takes a list of device locations""" 512c6dab2a8SThomas Monjalon global devices 513c6dab2a8SThomas Monjalon 51415f6aac7SAnatoly Burakov # a common user error is to forget to specify the driver the devices need to 51515f6aac7SAnatoly Burakov # be bound to. check if the driver is a valid device, and if it is, show 51615f6aac7SAnatoly Burakov # a meaningful error. 51715f6aac7SAnatoly Burakov try: 51815f6aac7SAnatoly Burakov dev_id_from_dev_name(driver) 51915f6aac7SAnatoly Burakov # if we've made it this far, this means that the "driver" was a valid 52015f6aac7SAnatoly Burakov # device string, so it's probably not a valid driver name. 52162d3ce60SStephen Hemminger sys.exit("Error: Driver '%s' does not look like a valid driver. " 52215f6aac7SAnatoly Burakov "Did you forget to specify the driver to bind devices to?" % driver) 52315f6aac7SAnatoly Burakov except ValueError: 52415f6aac7SAnatoly Burakov # driver generated error - it's not a valid device ID, so all is well 52515f6aac7SAnatoly Burakov pass 52615f6aac7SAnatoly Burakov 527681a6728SAnatoly Burakov # check if we're attempting to bind to a driver that isn't loaded 52843623124SPavan Nikhilesh if not module_is_loaded(driver.replace('-', '_')): 529681a6728SAnatoly Burakov sys.exit("Error: Driver '%s' is not loaded." % driver) 530681a6728SAnatoly Burakov 53115f6aac7SAnatoly Burakov try: 532c6dab2a8SThomas Monjalon dev_list = map(dev_id_from_dev_name, dev_list) 53315f6aac7SAnatoly Burakov except ValueError as ex: 53415f6aac7SAnatoly Burakov sys.exit(ex) 535c6dab2a8SThomas Monjalon 5366ca0f1c8SFidaullah Noonari # check for IOMMU support 5376ca0f1c8SFidaullah Noonari if driver == "vfio-pci" and not has_iommu(): 5386ca0f1c8SFidaullah Noonari check_noiommu_mode() 5396ca0f1c8SFidaullah Noonari 540c6dab2a8SThomas Monjalon for d in dev_list: 541c6dab2a8SThomas Monjalon bind_one(d, driver, force) 542c6dab2a8SThomas Monjalon 543e4839614SPavel Shirshov # For kernels < 3.15 when binding devices to a generic driver 5442fc35029SGuduri Prathyusha # (i.e. one that doesn't have a PCI ID table) using new_id, some devices 5452fc35029SGuduri Prathyusha # that are not bound to any other driver could be bound even if no one has 5462fc35029SGuduri Prathyusha # asked them to. hence, we check the list of drivers again, and see if 5472fc35029SGuduri Prathyusha # some of the previously-unbound devices were erroneously bound. 5481bb98a90SStephen Hemminger if not exists("/sys/bus/pci/devices/%s/driver_override" % d): 549c6dab2a8SThomas Monjalon for d in devices.keys(): 550c6dab2a8SThomas Monjalon # skip devices that were already bound or that we know should be bound 551c6dab2a8SThomas Monjalon if "Driver_str" in devices[d] or d in dev_list: 552c6dab2a8SThomas Monjalon continue 553c6dab2a8SThomas Monjalon 554c6dab2a8SThomas Monjalon # update information about this device 55562d3ce60SStephen Hemminger devices[d] = dict(devices[d].items() 55662d3ce60SStephen Hemminger + get_pci_device_details(d, True).items()) 557c6dab2a8SThomas Monjalon 558c6dab2a8SThomas Monjalon # check if updated information indicates that the device was bound 559c6dab2a8SThomas Monjalon if "Driver_str" in devices[d]: 560c6dab2a8SThomas Monjalon unbind_one(d, force) 561c6dab2a8SThomas Monjalon 562c6dab2a8SThomas Monjalon 563c6dab2a8SThomas Monjalondef display_devices(title, dev_list, extra_params=None): 564c6dab2a8SThomas Monjalon '''Displays to the user the details of a list of devices given in 565c6dab2a8SThomas Monjalon "dev_list". The "extra_params" parameter, if given, should contain a string 566c6dab2a8SThomas Monjalon with %()s fields in it for replacement by the named fields in each 567c6dab2a8SThomas Monjalon device's dictionary.''' 568c6dab2a8SThomas Monjalon strings = [] # this holds the strings to print. We sort before printing 569c6dab2a8SThomas Monjalon print("\n%s" % title) 570c6dab2a8SThomas Monjalon print("=" * len(title)) 571d58360c6SStephen Hemminger if not dev_list: 572c6dab2a8SThomas Monjalon strings.append("<none>") 573c6dab2a8SThomas Monjalon else: 574c6dab2a8SThomas Monjalon for dev in dev_list: 575c6dab2a8SThomas Monjalon if extra_params is not None: 576c3ce205dSGuduri Prathyusha strings.append("%s '%s %s' %s" % (dev["Slot"], 577c6dab2a8SThomas Monjalon dev["Device_str"], 578c3ce205dSGuduri Prathyusha dev["Device"], 579c6dab2a8SThomas Monjalon extra_params % dev)) 580c6dab2a8SThomas Monjalon else: 581c6dab2a8SThomas Monjalon strings.append("%s '%s'" % (dev["Slot"], dev["Device_str"])) 582c6dab2a8SThomas Monjalon # sort before printing, so that the entries appear in PCI order 583c6dab2a8SThomas Monjalon strings.sort() 584c6dab2a8SThomas Monjalon print("\n".join(strings)) # print one per line 585c6dab2a8SThomas Monjalon 58662d3ce60SStephen Hemminger 58736f66d1cSBruce Richardsondef show_device_status(devices_type, device_name, if_field=False): 588c6dab2a8SThomas Monjalon global dpdk_drivers 589c6dab2a8SThomas Monjalon kernel_drv = [] 590c6dab2a8SThomas Monjalon dpdk_drv = [] 591c6dab2a8SThomas Monjalon no_drv = [] 592c6dab2a8SThomas Monjalon 593*b456bf50SAnatoly Burakov print_numa = True # by default, assume we can print NUMA information 594*b456bf50SAnatoly Burakov 595c6dab2a8SThomas Monjalon # split our list of network devices into the three categories above 596c6dab2a8SThomas Monjalon for d in devices.keys(): 5978ad08a28SGuduri Prathyusha if device_type_match(devices[d], devices_type): 598*b456bf50SAnatoly Burakov print_numa &= "NUMANode" in devices[d] 599c6dab2a8SThomas Monjalon if not has_driver(d): 600c6dab2a8SThomas Monjalon no_drv.append(devices[d]) 601c6dab2a8SThomas Monjalon continue 602c6dab2a8SThomas Monjalon if devices[d]["Driver_str"] in dpdk_drivers: 603c6dab2a8SThomas Monjalon dpdk_drv.append(devices[d]) 604c6dab2a8SThomas Monjalon else: 605c6dab2a8SThomas Monjalon kernel_drv.append(devices[d]) 606c6dab2a8SThomas Monjalon 607109cb989SAnatoly Burakov n_devs = len(dpdk_drv) + len(kernel_drv) + len(no_drv) 608109cb989SAnatoly Burakov 609109cb989SAnatoly Burakov # don't bother displaying anything if there are no devices 610109cb989SAnatoly Burakov if n_devs == 0: 611109cb989SAnatoly Burakov msg = "No '%s' devices detected" % device_name 612109cb989SAnatoly Burakov print("") 613109cb989SAnatoly Burakov print(msg) 614109cb989SAnatoly Burakov print("".join('=' * len(msg))) 615109cb989SAnatoly Burakov return 616109cb989SAnatoly Burakov 617c6dab2a8SThomas Monjalon # print each category separately, so we can clearly see what's used by DPDK 618d58360c6SStephen Hemminger if dpdk_drv: 619a7d69cefSAnatoly Burakov extra_param = "drv=%(Driver_str)s unused=%(Module_str)s" 620a7d69cefSAnatoly Burakov if print_numa: 621a7d69cefSAnatoly Burakov extra_param = "numa_node=%(NUMANode)s " + extra_param 6228ad08a28SGuduri Prathyusha display_devices("%s devices using DPDK-compatible driver" % device_name, 623a7d69cefSAnatoly Burakov dpdk_drv, extra_param) 624d58360c6SStephen Hemminger if kernel_drv: 625a7d69cefSAnatoly Burakov extra_param = "drv=%(Driver_str)s unused=%(Module_str)s" 62636f66d1cSBruce Richardson if if_field: 627a7d69cefSAnatoly Burakov extra_param = "if=%(Interface)s " + extra_param 628a7d69cefSAnatoly Burakov if print_numa: 629a7d69cefSAnatoly Burakov extra_param = "numa_node=%(NUMANode)s " + extra_param 630828fe9deSAnatoly Burakov extra_param += " %(Active)s" 631a7d69cefSAnatoly Burakov display_devices("%s devices using kernel driver" % device_name, 632a7d69cefSAnatoly Burakov kernel_drv, extra_param) 633d58360c6SStephen Hemminger if no_drv: 634a7d69cefSAnatoly Burakov extra_param = "unused=%(Module_str)s" 635a7d69cefSAnatoly Burakov if print_numa: 636a7d69cefSAnatoly Burakov extra_param = "numa_node=%(NUMANode)s " + extra_param 637a7d69cefSAnatoly Burakov display_devices("Other %s devices" % device_name, no_drv, extra_param) 638c6dab2a8SThomas Monjalon 63962d3ce60SStephen Hemminger 640c7dd412bSGuduri Prathyushadef show_status(): 641c7dd412bSGuduri Prathyusha '''Function called when the script is passed the "--status" option. 642c7dd412bSGuduri Prathyusha Displays to the user what devices are bound to the igb_uio driver, the 643c7dd412bSGuduri Prathyusha kernel driver or to no driver''' 644c6dab2a8SThomas Monjalon 6450a3f92cdSStephen Hemminger if status_dev in ["net", "all"]: 64636f66d1cSBruce Richardson show_device_status(network_devices, "Network", if_field=True) 647b153c00bSFerruh Yigit 6480a3f92cdSStephen Hemminger if status_dev in ["baseband", "all"]: 64907488e29SNicolas Chautru show_device_status(baseband_devices, "Baseband") 65007488e29SNicolas Chautru 6510a3f92cdSStephen Hemminger if status_dev in ["crypto", "all"]: 652c7dd412bSGuduri Prathyusha show_device_status(crypto_devices, "Crypto") 653b153c00bSFerruh Yigit 6549afeef14SKevin Laatz if status_dev in ["dma", "all"]: 6559afeef14SKevin Laatz show_device_status(dma_devices, "DMA") 6569afeef14SKevin Laatz 6570a3f92cdSStephen Hemminger if status_dev in ["event", "all"]: 65832a02dbfSGuduri Prathyusha show_device_status(eventdev_devices, "Eventdev") 659b153c00bSFerruh Yigit 6600a3f92cdSStephen Hemminger if status_dev in ["mempool", "all"]: 66180a1858dSGuduri Prathyusha show_device_status(mempool_devices, "Mempool") 662c6dab2a8SThomas Monjalon 6630a3f92cdSStephen Hemminger if status_dev in ["compress", "all"]: 6649d35895eSSunila Sahu show_device_status(compress_devices, "Compress") 6659d35895eSSunila Sahu 6660a3f92cdSStephen Hemminger if status_dev in ["misc", "all"]: 66712d4777aSBruce Richardson show_device_status(misc_devices, "Misc (rawdev)") 6689d35895eSSunila Sahu 6690a3f92cdSStephen Hemminger if status_dev in ["regex", "all"]: 67009f84c9aSGuy Kaneti show_device_status(regex_devices, "Regex") 67109f84c9aSGuy Kaneti 672b9aaa675SSrikanth Yalavarthi if status_dev in ["ml", "all"]: 673b9aaa675SSrikanth Yalavarthi show_device_status(ml_devices, "ML") 674b9aaa675SSrikanth Yalavarthi 675781eafc9SBruce Richardson 676781eafc9SBruce Richardsondef pci_glob(arg): 677781eafc9SBruce Richardson '''Returns a list containing either: 678781eafc9SBruce Richardson * List of PCI B:D:F matching arg, using shell wildcards e.g. 80:04.* 679781eafc9SBruce Richardson * Only the passed arg if matching list is empty''' 680781eafc9SBruce Richardson sysfs_path = "/sys/bus/pci/devices" 681781eafc9SBruce Richardson for _glob in [arg, '0000:' + arg]: 682781eafc9SBruce Richardson paths = [basename(path) for path in glob(path_join(sysfs_path, _glob))] 683781eafc9SBruce Richardson if paths: 684781eafc9SBruce Richardson return paths 685781eafc9SBruce Richardson return [arg] 686781eafc9SBruce Richardson 687781eafc9SBruce Richardson 688c6dab2a8SThomas Monjalondef parse_args(): 689c6dab2a8SThomas Monjalon '''Parses the command-line arguments given by the user and takes the 690c6dab2a8SThomas Monjalon appropriate action for each''' 691c6dab2a8SThomas Monjalon global b_flag 692c6dab2a8SThomas Monjalon global status_flag 693b153c00bSFerruh Yigit global status_dev 694c6dab2a8SThomas Monjalon global force_flag 6956ca0f1c8SFidaullah Noonari global noiommu_flag 696c6dab2a8SThomas Monjalon global args 697c6dab2a8SThomas Monjalon 69881255f27SStephen Hemminger parser = argparse.ArgumentParser( 69981255f27SStephen Hemminger description='Utility to bind and unbind devices from Linux kernel', 70081255f27SStephen Hemminger formatter_class=argparse.RawDescriptionHelpFormatter, 70181255f27SStephen Hemminger epilog=""" 70281255f27SStephen HemmingerExamples: 70381255f27SStephen Hemminger--------- 704c6dab2a8SThomas Monjalon 70581255f27SStephen HemmingerTo display current device status: 70681255f27SStephen Hemminger %(prog)s --status 70781255f27SStephen Hemminger 70881255f27SStephen HemmingerTo display current network device status: 70981255f27SStephen Hemminger %(prog)s --status-dev net 71081255f27SStephen Hemminger 71181255f27SStephen HemmingerTo bind eth1 from the current driver and move to use vfio-pci 71281255f27SStephen Hemminger %(prog)s --bind=vfio-pci eth1 71381255f27SStephen Hemminger 71481255f27SStephen HemmingerTo unbind 0000:01:00.0 from using any driver 71581255f27SStephen Hemminger %(prog)s -u 0000:01:00.0 71681255f27SStephen Hemminger 71781255f27SStephen HemmingerTo bind 0000:02:00.0 and 0000:02:00.1 to the ixgbe kernel driver 71881255f27SStephen Hemminger %(prog)s -b ixgbe 02:00.0 02:00.1 71981255f27SStephen Hemminger""") 72081255f27SStephen Hemminger 72181255f27SStephen Hemminger parser.add_argument( 72281255f27SStephen Hemminger '-s', 72381255f27SStephen Hemminger '--status', 72481255f27SStephen Hemminger action='store_true', 72581255f27SStephen Hemminger help="Print the current status of all known devices.") 72681255f27SStephen Hemminger parser.add_argument( 72781255f27SStephen Hemminger '--status-dev', 72881255f27SStephen Hemminger help="Print the status of given device group.", 7299afeef14SKevin Laatz choices=['baseband', 'compress', 'crypto', 'dma', 'event', 730b9aaa675SSrikanth Yalavarthi 'mempool', 'misc', 'net', 'regex', 'ml']) 73181255f27SStephen Hemminger bind_group = parser.add_mutually_exclusive_group() 73281255f27SStephen Hemminger bind_group.add_argument( 73381255f27SStephen Hemminger '-b', 73481255f27SStephen Hemminger '--bind', 73581255f27SStephen Hemminger metavar='DRIVER', 73681255f27SStephen Hemminger help="Select the driver to use or \"none\" to unbind the device") 73781255f27SStephen Hemminger bind_group.add_argument( 73881255f27SStephen Hemminger '-u', 73981255f27SStephen Hemminger '--unbind', 74081255f27SStephen Hemminger action='store_true', 74181255f27SStephen Hemminger help="Unbind a device (equivalent to \"-b none\")") 74281255f27SStephen Hemminger parser.add_argument( 7436ca0f1c8SFidaullah Noonari '--noiommu-mode', 7446ca0f1c8SFidaullah Noonari action='store_true', 7456ca0f1c8SFidaullah Noonari help="If IOMMU is not available, enable no IOMMU mode for VFIO drivers") 7466ca0f1c8SFidaullah Noonari parser.add_argument( 74781255f27SStephen Hemminger '--force', 74881255f27SStephen Hemminger action='store_true', 74981255f27SStephen Hemminger help=""" 75081255f27SStephen HemmingerOverride restriction on binding devices in use by Linux" 75181255f27SStephen HemmingerWARNING: This can lead to loss of network connection and should be used with caution. 75281255f27SStephen Hemminger""") 75381255f27SStephen Hemminger parser.add_argument( 75481255f27SStephen Hemminger 'devices', 75581255f27SStephen Hemminger metavar='DEVICE', 75681255f27SStephen Hemminger nargs='*', 75781255f27SStephen Hemminger help=""" 75881255f27SStephen HemmingerDevice specified as PCI "domain:bus:slot.func" syntax or "bus:slot.func" syntax. 75981255f27SStephen HemmingerFor devices bound to Linux kernel drivers, they may be referred to by interface name. 76081255f27SStephen Hemminger""") 76181255f27SStephen Hemminger 76281255f27SStephen Hemminger opt = parser.parse_args() 76381255f27SStephen Hemminger 76481255f27SStephen Hemminger if opt.status_dev: 765b153c00bSFerruh Yigit status_flag = True 76681255f27SStephen Hemminger status_dev = opt.status_dev 76781255f27SStephen Hemminger if opt.status: 768c6dab2a8SThomas Monjalon status_flag = True 769b153c00bSFerruh Yigit status_dev = "all" 77081255f27SStephen Hemminger if opt.force: 771c6dab2a8SThomas Monjalon force_flag = True 7726ca0f1c8SFidaullah Noonari if opt.noiommu_mode: 7736ca0f1c8SFidaullah Noonari noiommu_flag = True 77481255f27SStephen Hemminger if opt.bind: 77581255f27SStephen Hemminger b_flag = opt.bind 77681255f27SStephen Hemminger elif opt.unbind: 777c6dab2a8SThomas Monjalon b_flag = "none" 77881255f27SStephen Hemminger args = opt.devices 77981255f27SStephen Hemminger 78081255f27SStephen Hemminger if not b_flag and not status_flag: 78181255f27SStephen Hemminger print("Error: No action specified for devices. " 78281255f27SStephen Hemminger "Please give a --bind, --ubind or --status option", 78381255f27SStephen Hemminger file=sys.stderr) 78481255f27SStephen Hemminger parser.print_usage() 78581255f27SStephen Hemminger sys.exit(1) 78681255f27SStephen Hemminger 78781255f27SStephen Hemminger if b_flag and not args: 78881255f27SStephen Hemminger print("Error: No devices specified.", file=sys.stderr) 78981255f27SStephen Hemminger parser.print_usage() 79081255f27SStephen Hemminger sys.exit(1) 791c6dab2a8SThomas Monjalon 792781eafc9SBruce Richardson # resolve any PCI globs in the args 793781eafc9SBruce Richardson new_args = [] 794781eafc9SBruce Richardson for arg in args: 795781eafc9SBruce Richardson new_args.extend(pci_glob(arg)) 796781eafc9SBruce Richardson args = new_args 797c6dab2a8SThomas Monjalon 79862d3ce60SStephen Hemminger 799c6dab2a8SThomas Monjalondef do_arg_actions(): 800c6dab2a8SThomas Monjalon '''do the actual action requested by the user''' 801c6dab2a8SThomas Monjalon global b_flag 802c6dab2a8SThomas Monjalon global status_flag 803c6dab2a8SThomas Monjalon global force_flag 804c6dab2a8SThomas Monjalon global args 805c6dab2a8SThomas Monjalon 8060a3f92cdSStephen Hemminger if b_flag in ["none", "None"]: 807c6dab2a8SThomas Monjalon unbind_all(args, force_flag) 808c6dab2a8SThomas Monjalon elif b_flag is not None: 809c6dab2a8SThomas Monjalon bind_all(args, b_flag, force_flag) 810c6dab2a8SThomas Monjalon if status_flag: 811c6dab2a8SThomas Monjalon if b_flag is not None: 812ea9f00f7SGuduri Prathyusha clear_data() 8138ad08a28SGuduri Prathyusha # refresh if we have changed anything 8148ad08a28SGuduri Prathyusha get_device_details(network_devices) 81507488e29SNicolas Chautru get_device_details(baseband_devices) 8168ad08a28SGuduri Prathyusha get_device_details(crypto_devices) 8179afeef14SKevin Laatz get_device_details(dma_devices) 81832a02dbfSGuduri Prathyusha get_device_details(eventdev_devices) 81980a1858dSGuduri Prathyusha get_device_details(mempool_devices) 8209d35895eSSunila Sahu get_device_details(compress_devices) 82109f84c9aSGuy Kaneti get_device_details(regex_devices) 822b9aaa675SSrikanth Yalavarthi get_device_details(ml_devices) 82312d4777aSBruce Richardson get_device_details(misc_devices) 824c6dab2a8SThomas Monjalon show_status() 825c6dab2a8SThomas Monjalon 826c6dab2a8SThomas Monjalon 827c6dab2a8SThomas Monjalondef main(): 828c6dab2a8SThomas Monjalon '''program main function''' 8291a5a9cb3SAnatoly Burakov # check if lspci is installed, suppress any output 8301a5a9cb3SAnatoly Burakov with open(os.devnull, 'w') as devnull: 8311a5a9cb3SAnatoly Burakov ret = subprocess.call(['which', 'lspci'], 8321a5a9cb3SAnatoly Burakov stdout=devnull, stderr=devnull) 8331a5a9cb3SAnatoly Burakov if ret != 0: 8342804529fSAnatoly Burakov sys.exit("'lspci' not found - please install 'pciutils'") 835c6dab2a8SThomas Monjalon parse_args() 836c6dab2a8SThomas Monjalon check_modules() 837ea9f00f7SGuduri Prathyusha clear_data() 8388ad08a28SGuduri Prathyusha get_device_details(network_devices) 83907488e29SNicolas Chautru get_device_details(baseband_devices) 8408ad08a28SGuduri Prathyusha get_device_details(crypto_devices) 8419afeef14SKevin Laatz get_device_details(dma_devices) 84232a02dbfSGuduri Prathyusha get_device_details(eventdev_devices) 84380a1858dSGuduri Prathyusha get_device_details(mempool_devices) 8449d35895eSSunila Sahu get_device_details(compress_devices) 84509f84c9aSGuy Kaneti get_device_details(regex_devices) 846b9aaa675SSrikanth Yalavarthi get_device_details(ml_devices) 84712d4777aSBruce Richardson get_device_details(misc_devices) 848c6dab2a8SThomas Monjalon do_arg_actions() 849c6dab2a8SThomas Monjalon 85062d3ce60SStephen Hemminger 851c6dab2a8SThomas Monjalonif __name__ == "__main__": 852c6dab2a8SThomas Monjalon main() 853