xref: /dpdk/usertools/dpdk-devbind.py (revision 33e71acf)
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}
51fb73eb2fSChengwen Feng
52240078c0STimothy McDanielintel_dlb = {'Class': '0b', 'Vendor': '8086', 'Device': '270b,2710,2714',
53240078c0STimothy McDaniel             'SVendor': None, 'SDevice': None}
54c358ba7aSStephen Hemmingerintel_ioat_bdw = {'Class': '08', 'Vendor': '8086',
55c358ba7aSStephen Hemminger                  'Device': '6f20,6f21,6f22,6f23,6f24,6f25,6f26,6f27,6f2e,6f2f',
5612d4777aSBruce Richardson                  'SVendor': None, 'SDevice': None}
5712d4777aSBruce Richardsonintel_ioat_skx = {'Class': '08', 'Vendor': '8086', 'Device': '2021',
5812d4777aSBruce Richardson                  'SVendor': None, 'SDevice': None}
59299e282fSRadu Nicolauintel_ioat_icx = {'Class': '08', 'Vendor': '8086', 'Device': '0b00',
60299e282fSRadu Nicolau                  'SVendor': None, 'SDevice': None}
6143f9b521SKevin Laatzintel_idxd_spr = {'Class': '08', 'Vendor': '8086', 'Device': '0b25',
6243f9b521SKevin Laatz                  'SVendor': None, 'SDevice': None}
63034c328eSXiaoyun Liintel_ntb_skx = {'Class': '06', 'Vendor': '8086', 'Device': '201c',
64034c328eSXiaoyun Li                 'SVendor': None, 'SDevice': None}
65f5057be3SXiaoyun Liintel_ntb_icx = {'Class': '06', 'Vendor': '8086', 'Device': '347e',
66f5057be3SXiaoyun Li                 'SVendor': None, 'SDevice': None}
6712d4777aSBruce Richardson
68*33e71acfSJerin Jacobcnxk_sso = {'Class': '08', 'Vendor': '177d', 'Device': 'a0f9,a0fa',
692ff80151SRadha Mohan Chintakuntla                 'SVendor': None, 'SDevice': None}
70*33e71acfSJerin Jacobcnxk_npa = {'Class': '08', 'Vendor': '177d', 'Device': 'a0fb,a0fc',
712ff80151SRadha Mohan Chintakuntla                 'SVendor': None, 'SDevice': None}
72*33e71acfSJerin Jacobcn9k_ree = {'Class': '08', 'Vendor': '177d', 'Device': 'a0f4',
732ff80151SRadha Mohan Chintakuntla                 'SVendor': None, 'SDevice': None}
742ff80151SRadha Mohan Chintakuntla
75c01c748eSRosen Xunetwork_devices = [network_class, cavium_pkx, avp_vnic, ifpga_class]
7607488e29SNicolas Chautrubaseband_devices = [acceleration_class]
778ad08a28SGuduri Prathyushacrypto_devices = [encryption_class, intel_processor_class]
782ff80151SRadha Mohan Chintakuntladma_devices = [cnxk_dma, hisilicon_dma,
79fb73eb2fSChengwen Feng               intel_idxd_spr, intel_ioat_bdw, intel_ioat_icx, intel_ioat_skx]
80*33e71acfSJerin Jacobeventdev_devices = [cavium_sso, cavium_tim, intel_dlb, cnxk_sso]
81*33e71acfSJerin Jacobmempool_devices = [cavium_fpa, cnxk_npa]
829d35895eSSunila Sahucompress_devices = [cavium_zip]
83*33e71acfSJerin Jacobregex_devices = [cn9k_ree]
842ff80151SRadha Mohan Chintakuntlamisc_devices = [cnxk_bphy, cnxk_bphy_cgx, cnxk_inl_dev,
852ff80151SRadha Mohan Chintakuntla                intel_ntb_skx, intel_ntb_icx]
86c6dab2a8SThomas Monjalon
87c6dab2a8SThomas Monjalon# global dict ethernet devices present. Dictionary indexed by PCI address.
88c6dab2a8SThomas Monjalon# Each device within this is itself a dictionary of device properties
89c6dab2a8SThomas Monjalondevices = {}
90c6dab2a8SThomas Monjalon# list of supported DPDK drivers
91c6dab2a8SThomas Monjalondpdk_drivers = ["igb_uio", "vfio-pci", "uio_pci_generic"]
92681a6728SAnatoly Burakov# list of currently loaded kernel modules
93681a6728SAnatoly Burakovloaded_modules = None
94c6dab2a8SThomas Monjalon
95c6dab2a8SThomas Monjalon# command-line arg flags
96c6dab2a8SThomas Monjalonb_flag = None
97c6dab2a8SThomas Monjalonstatus_flag = False
98c6dab2a8SThomas Monjalonforce_flag = False
99c6dab2a8SThomas Monjalonargs = []
100c6dab2a8SThomas Monjalon
10162d3ce60SStephen Hemminger
102681a6728SAnatoly Burakov# check if a specific kernel module is loaded
103681a6728SAnatoly Burakovdef module_is_loaded(module):
104681a6728SAnatoly Burakov    global loaded_modules
105681a6728SAnatoly Burakov
10643623124SPavan Nikhilesh    if module == 'vfio_pci':
10743623124SPavan Nikhilesh        module = 'vfio-pci'
10843623124SPavan Nikhilesh
109681a6728SAnatoly Burakov    if loaded_modules:
110681a6728SAnatoly Burakov        return module in loaded_modules
111681a6728SAnatoly Burakov
112681a6728SAnatoly Burakov    # Get list of sysfs modules (both built-in and dynamically loaded)
113681a6728SAnatoly Burakov    sysfs_path = '/sys/module/'
114681a6728SAnatoly Burakov
115681a6728SAnatoly Burakov    # Get the list of directories in sysfs_path
116681a6728SAnatoly Burakov    sysfs_mods = [m for m in os.listdir(sysfs_path)
117681a6728SAnatoly Burakov                  if os.path.isdir(os.path.join(sysfs_path, m))]
118681a6728SAnatoly Burakov
119681a6728SAnatoly Burakov    # special case for vfio_pci (module is named vfio-pci,
120681a6728SAnatoly Burakov    # but its .ko is named vfio_pci)
121681a6728SAnatoly Burakov    sysfs_mods = [a if a != 'vfio_pci' else 'vfio-pci' for a in sysfs_mods]
122681a6728SAnatoly Burakov
123681a6728SAnatoly Burakov    loaded_modules = sysfs_mods
124681a6728SAnatoly Burakov
1257a016af4SYongxin Liu    # add built-in modules as loaded
1267a016af4SYongxin Liu    release = platform.uname().release
1277a016af4SYongxin Liu    filename = os.path.join("/lib/modules/", release, "modules.builtin")
1287a016af4SYongxin Liu    if os.path.exists(filename):
1297a016af4SYongxin Liu        try:
1307a016af4SYongxin Liu            with open(filename) as f:
1317a016af4SYongxin Liu                loaded_modules += [os.path.splitext(os.path.basename(mod))[0] for mod in f]
1327a016af4SYongxin Liu        except IOError:
1337a016af4SYongxin Liu            print("Warning: cannot read list of built-in kernel modules")
1347a016af4SYongxin Liu
1357a016af4SYongxin Liu    return module in loaded_modules
136681a6728SAnatoly Burakov
137c6dab2a8SThomas Monjalon
138c6dab2a8SThomas Monjalondef check_modules():
139c6dab2a8SThomas Monjalon    '''Checks that igb_uio is loaded'''
140c6dab2a8SThomas Monjalon    global dpdk_drivers
141c6dab2a8SThomas Monjalon
142c6dab2a8SThomas Monjalon    # list of supported modules
143c6dab2a8SThomas Monjalon    mods = [{"Name": driver, "Found": False} for driver in dpdk_drivers]
144c6dab2a8SThomas Monjalon
145c6dab2a8SThomas Monjalon    # first check if module is loaded
146c6dab2a8SThomas Monjalon    for mod in mods:
147681a6728SAnatoly Burakov        if module_is_loaded(mod["Name"]):
148c6dab2a8SThomas Monjalon            mod["Found"] = True
149c6dab2a8SThomas Monjalon
150c6dab2a8SThomas Monjalon    # check if we have at least one loaded module
151c6dab2a8SThomas Monjalon    if True not in [mod["Found"] for mod in mods] and b_flag is not None:
1522804529fSAnatoly Burakov        print("Warning: no supported DPDK kernel modules are loaded", file=sys.stderr)
153c6dab2a8SThomas Monjalon
154c6dab2a8SThomas Monjalon    # change DPDK driver list to only contain drivers that are loaded
155c6dab2a8SThomas Monjalon    dpdk_drivers = [mod["Name"] for mod in mods if mod["Found"]]
156c6dab2a8SThomas Monjalon
157c6dab2a8SThomas Monjalon
158c6dab2a8SThomas Monjalondef has_driver(dev_id):
159c6dab2a8SThomas Monjalon    '''return true if a device is assigned to a driver. False otherwise'''
160c6dab2a8SThomas Monjalon    return "Driver_str" in devices[dev_id]
161c6dab2a8SThomas Monjalon
162c6dab2a8SThomas Monjalon
163c3ce205dSGuduri Prathyushadef get_pci_device_details(dev_id, probe_lspci):
164c6dab2a8SThomas Monjalon    '''This function gets additional details for a PCI device'''
165c6dab2a8SThomas Monjalon    device = {}
166c6dab2a8SThomas Monjalon
167c3ce205dSGuduri Prathyusha    if probe_lspci:
1683f6f8362SLouise Kilheeney        extra_info = subprocess.check_output(["lspci", "-vmmks", dev_id]).splitlines()
169c6dab2a8SThomas Monjalon        # parse lspci details
170c6dab2a8SThomas Monjalon        for line in extra_info:
171d58360c6SStephen Hemminger            if not line:
172c6dab2a8SThomas Monjalon                continue
17308ab6cd3SChristos Ricudis            name, value = line.decode("utf8").split("\t", 1)
174c6dab2a8SThomas Monjalon            name = name.strip(":") + "_str"
175c6dab2a8SThomas Monjalon            device[name] = value
176c6dab2a8SThomas Monjalon    # check for a unix interface name
177c6dab2a8SThomas Monjalon    device["Interface"] = ""
178c6dab2a8SThomas Monjalon    for base, dirs, _ in os.walk("/sys/bus/pci/devices/%s/" % dev_id):
179c6dab2a8SThomas Monjalon        if "net" in dirs:
180c6dab2a8SThomas Monjalon            device["Interface"] = \
181c6dab2a8SThomas Monjalon                ",".join(os.listdir(os.path.join(base, "net")))
182c6dab2a8SThomas Monjalon            break
183c6dab2a8SThomas Monjalon    # check if a port is used for ssh connection
184c6dab2a8SThomas Monjalon    device["Ssh_if"] = False
185c6dab2a8SThomas Monjalon    device["Active"] = ""
186c6dab2a8SThomas Monjalon
187c6dab2a8SThomas Monjalon    return device
188c6dab2a8SThomas Monjalon
18962d3ce60SStephen Hemminger
190ea9f00f7SGuduri Prathyushadef clear_data():
191ea9f00f7SGuduri Prathyusha    '''This function clears any old data'''
19293b93bebSTimothy Redaelli    global devices
193ea9f00f7SGuduri Prathyusha    devices = {}
194c6dab2a8SThomas Monjalon
19562d3ce60SStephen Hemminger
196ea9f00f7SGuduri Prathyushadef get_device_details(devices_type):
197c6dab2a8SThomas Monjalon    '''This function populates the "devices" dictionary. The keys used are
198c6dab2a8SThomas Monjalon    the pci addresses (domain:bus:slot.func). The values are themselves
199c6dab2a8SThomas Monjalon    dictionaries - one for each NIC.'''
200c6dab2a8SThomas Monjalon    global devices
201c6dab2a8SThomas Monjalon    global dpdk_drivers
202c6dab2a8SThomas Monjalon
203c6dab2a8SThomas Monjalon    # first loop through and read details for all devices
204c3ce205dSGuduri Prathyusha    # request machine readable format, with numeric IDs and String
205c6dab2a8SThomas Monjalon    dev = {}
2063f6f8362SLouise Kilheeney    dev_lines = subprocess.check_output(["lspci", "-Dvmmnnk"]).splitlines()
207c6dab2a8SThomas Monjalon    for dev_line in dev_lines:
208d58360c6SStephen Hemminger        if not dev_line:
2098ad08a28SGuduri Prathyusha            if device_type_match(dev, devices_type):
2108ad08a28SGuduri Prathyusha                # Replace "Driver" with "Driver_str" to have consistency of
2118ad08a28SGuduri Prathyusha                # of dictionary key names
212c3ce205dSGuduri Prathyusha                if "Driver" in dev.keys():
213c3ce205dSGuduri Prathyusha                    dev["Driver_str"] = dev.pop("Driver")
214c76a10ecSAnatoly Burakov                if "Module" in dev.keys():
215c76a10ecSAnatoly Burakov                    dev["Module_str"] = dev.pop("Module")
216c6dab2a8SThomas Monjalon                # use dict to make copy of dev
217c6dab2a8SThomas Monjalon                devices[dev["Slot"]] = dict(dev)
218c3ce205dSGuduri Prathyusha            # Clear previous device's data
219c3ce205dSGuduri Prathyusha            dev = {}
220c6dab2a8SThomas Monjalon        else:
22108ab6cd3SChristos Ricudis            name, value = dev_line.decode("utf8").split("\t", 1)
222c3ce205dSGuduri Prathyusha            value_list = value.rsplit(' ', 1)
223d58360c6SStephen Hemminger            if value_list:
224c3ce205dSGuduri Prathyusha                # String stored in <name>_str
225c3ce205dSGuduri Prathyusha                dev[name.rstrip(":") + '_str'] = value_list[0]
226c3ce205dSGuduri Prathyusha            # Numeric IDs
227c3ce205dSGuduri Prathyusha            dev[name.rstrip(":")] = value_list[len(value_list) - 1] \
228c3ce205dSGuduri Prathyusha                .rstrip("]").lstrip("[")
229c6dab2a8SThomas Monjalon
2308ad08a28SGuduri Prathyusha    if devices_type == network_devices:
231c6dab2a8SThomas Monjalon        # check what is the interface if any for an ssh connection if
232c6dab2a8SThomas Monjalon        # any to this host, so we can mark it later.
233c6dab2a8SThomas Monjalon        ssh_if = []
2343f6f8362SLouise Kilheeney        route = subprocess.check_output(["ip", "-o", "route"])
235c6dab2a8SThomas Monjalon        # filter out all lines for 169.254 routes
236c6dab2a8SThomas Monjalon        route = "\n".join(filter(lambda ln: not ln.startswith("169.254"),
237c6dab2a8SThomas Monjalon                                 route.decode().splitlines()))
238c6dab2a8SThomas Monjalon        rt_info = route.split()
239c6dab2a8SThomas Monjalon        for i in range(len(rt_info) - 1):
240c6dab2a8SThomas Monjalon            if rt_info[i] == "dev":
241c6dab2a8SThomas Monjalon                ssh_if.append(rt_info[i + 1])
242c6dab2a8SThomas Monjalon
243c6dab2a8SThomas Monjalon    # based on the basic info, get extended text details
244c6dab2a8SThomas Monjalon    for d in devices.keys():
2458ad08a28SGuduri Prathyusha        if not device_type_match(devices[d], devices_type):
246617d9052SYoni Gilad            continue
247617d9052SYoni Gilad
248c6dab2a8SThomas Monjalon        # get additional info and add it to existing data
249c6dab2a8SThomas Monjalon        devices[d] = devices[d].copy()
250c3ce205dSGuduri Prathyusha        # No need to probe lspci
251c3ce205dSGuduri Prathyusha        devices[d].update(get_pci_device_details(d, False).items())
252c6dab2a8SThomas Monjalon
2538ad08a28SGuduri Prathyusha        if devices_type == network_devices:
254ea9f00f7SGuduri Prathyusha            for _if in ssh_if:
255ea9f00f7SGuduri Prathyusha                if _if in devices[d]["Interface"].split(","):
256ea9f00f7SGuduri Prathyusha                    devices[d]["Ssh_if"] = True
257ea9f00f7SGuduri Prathyusha                    devices[d]["Active"] = "*Active*"
258ea9f00f7SGuduri Prathyusha                    break
259ea9f00f7SGuduri Prathyusha
260c6dab2a8SThomas Monjalon        # add igb_uio to list of supporting modules if needed
261c6dab2a8SThomas Monjalon        if "Module_str" in devices[d]:
262c6dab2a8SThomas Monjalon            for driver in dpdk_drivers:
263c6dab2a8SThomas Monjalon                if driver not in devices[d]["Module_str"]:
264c6dab2a8SThomas Monjalon                    devices[d]["Module_str"] = \
265c6dab2a8SThomas Monjalon                        devices[d]["Module_str"] + ",%s" % driver
266c6dab2a8SThomas Monjalon        else:
267c6dab2a8SThomas Monjalon            devices[d]["Module_str"] = ",".join(dpdk_drivers)
268c6dab2a8SThomas Monjalon
269c6dab2a8SThomas Monjalon        # make sure the driver and module strings do not have any duplicates
270c6dab2a8SThomas Monjalon        if has_driver(d):
271c6dab2a8SThomas Monjalon            modules = devices[d]["Module_str"].split(",")
272c6dab2a8SThomas Monjalon            if devices[d]["Driver_str"] in modules:
273c6dab2a8SThomas Monjalon                modules.remove(devices[d]["Driver_str"])
274c6dab2a8SThomas Monjalon                devices[d]["Module_str"] = ",".join(modules)
275c6dab2a8SThomas Monjalon
276c6dab2a8SThomas Monjalon
2778ad08a28SGuduri Prathyushadef device_type_match(dev, devices_type):
2788ad08a28SGuduri Prathyusha    for i in range(len(devices_type)):
2798ad08a28SGuduri Prathyusha        param_count = len(
2808ad08a28SGuduri Prathyusha            [x for x in devices_type[i].values() if x is not None])
2818ad08a28SGuduri Prathyusha        match_count = 0
2828ad08a28SGuduri Prathyusha        if dev["Class"][0:2] == devices_type[i]["Class"]:
2838ad08a28SGuduri Prathyusha            match_count = match_count + 1
2848ad08a28SGuduri Prathyusha            for key in devices_type[i].keys():
2858ad08a28SGuduri Prathyusha                if key != 'Class' and devices_type[i][key]:
2868ad08a28SGuduri Prathyusha                    value_list = devices_type[i][key].split(',')
2878ad08a28SGuduri Prathyusha                    for value in value_list:
2888ad08a28SGuduri Prathyusha                        if value.strip(' ') == dev[key]:
2898ad08a28SGuduri Prathyusha                            match_count = match_count + 1
2908ad08a28SGuduri Prathyusha            # count must be the number of non None parameters to match
2918ad08a28SGuduri Prathyusha            if match_count == param_count:
2928ad08a28SGuduri Prathyusha                return True
2938ad08a28SGuduri Prathyusha    return False
2948ad08a28SGuduri Prathyusha
29562d3ce60SStephen Hemminger
296c6dab2a8SThomas Monjalondef dev_id_from_dev_name(dev_name):
297c6dab2a8SThomas Monjalon    '''Take a device "name" - a string passed in by user to identify a NIC
298c6dab2a8SThomas Monjalon    device, and determine the device id - i.e. the domain:bus:slot.func - for
299c6dab2a8SThomas Monjalon    it, which can then be used to index into the devices array'''
300c6dab2a8SThomas Monjalon
301c6dab2a8SThomas Monjalon    # check if it's already a suitable index
302c6dab2a8SThomas Monjalon    if dev_name in devices:
303c6dab2a8SThomas Monjalon        return dev_name
304c6dab2a8SThomas Monjalon    # check if it's an index just missing the domain part
305b5685e39SStephen Hemminger    if "0000:" + dev_name in devices:
306c6dab2a8SThomas Monjalon        return "0000:" + dev_name
307b5685e39SStephen Hemminger
308c6dab2a8SThomas Monjalon    # check if it's an interface name, e.g. eth1
309c6dab2a8SThomas Monjalon    for d in devices.keys():
310c6dab2a8SThomas Monjalon        if dev_name in devices[d]["Interface"].split(","):
311c6dab2a8SThomas Monjalon            return devices[d]["Slot"]
312c6dab2a8SThomas Monjalon    # if nothing else matches - error
31315f6aac7SAnatoly Burakov    raise ValueError("Unknown device: %s. "
314c6dab2a8SThomas Monjalon                     "Please specify device in \"bus:slot.func\" format" % dev_name)
315c6dab2a8SThomas Monjalon
316c6dab2a8SThomas Monjalon
317c6dab2a8SThomas Monjalondef unbind_one(dev_id, force):
318c6dab2a8SThomas Monjalon    '''Unbind the device identified by "dev_id" from its current driver'''
319c6dab2a8SThomas Monjalon    dev = devices[dev_id]
320c6dab2a8SThomas Monjalon    if not has_driver(dev_id):
3212804529fSAnatoly Burakov        print("Notice: %s %s %s is not currently managed by any driver" %
3222804529fSAnatoly Burakov              (dev["Slot"], dev["Device_str"], dev["Interface"]), file=sys.stderr)
323c6dab2a8SThomas Monjalon        return
324c6dab2a8SThomas Monjalon
325c6dab2a8SThomas Monjalon    # prevent us disconnecting ourselves
326c6dab2a8SThomas Monjalon    if dev["Ssh_if"] and not force:
3272804529fSAnatoly Burakov        print("Warning: routing table indicates that interface %s is active. "
3282804529fSAnatoly Burakov              "Skipping unbind" % dev_id, file=sys.stderr)
329c6dab2a8SThomas Monjalon        return
330c6dab2a8SThomas Monjalon
331c6dab2a8SThomas Monjalon    # write to /sys to unbind
332c6dab2a8SThomas Monjalon    filename = "/sys/bus/pci/drivers/%s/unbind" % dev["Driver_str"]
333c6dab2a8SThomas Monjalon    try:
334c6dab2a8SThomas Monjalon        f = open(filename, "a")
33562d3ce60SStephen Hemminger    except OSError as err:
33662d3ce60SStephen Hemminger        sys.exit("Error: unbind failed for %s - Cannot open %s: %s" %
33762d3ce60SStephen Hemminger                 (dev_id, filename, err))
338c6dab2a8SThomas Monjalon    f.write(dev_id)
339c6dab2a8SThomas Monjalon    f.close()
340c6dab2a8SThomas Monjalon
341c6dab2a8SThomas Monjalon
342c6dab2a8SThomas Monjalondef bind_one(dev_id, driver, force):
343c6dab2a8SThomas Monjalon    '''Bind the device given by "dev_id" to the driver "driver". If the device
344c6dab2a8SThomas Monjalon    is already bound to a different driver, it will be unbound first'''
345c6dab2a8SThomas Monjalon    dev = devices[dev_id]
346c6dab2a8SThomas Monjalon    saved_driver = None  # used to rollback any unbind in case of failure
347c6dab2a8SThomas Monjalon
348c6dab2a8SThomas Monjalon    # prevent disconnection of our ssh session
349c6dab2a8SThomas Monjalon    if dev["Ssh_if"] and not force:
3502804529fSAnatoly Burakov        print("Warning: routing table indicates that interface %s is active. "
3512804529fSAnatoly Burakov              "Not modifying" % dev_id, file=sys.stderr)
352c6dab2a8SThomas Monjalon        return
353c6dab2a8SThomas Monjalon
354c6dab2a8SThomas Monjalon    # unbind any existing drivers we don't want
355c6dab2a8SThomas Monjalon    if has_driver(dev_id):
356c6dab2a8SThomas Monjalon        if dev["Driver_str"] == driver:
3572804529fSAnatoly Burakov            print("Notice: %s already bound to driver %s, skipping" %
3582804529fSAnatoly Burakov                  (dev_id, driver), file=sys.stderr)
359c6dab2a8SThomas Monjalon            return
360c6dab2a8SThomas Monjalon        saved_driver = dev["Driver_str"]
361c6dab2a8SThomas Monjalon        unbind_one(dev_id, force)
362c6dab2a8SThomas Monjalon        dev["Driver_str"] = ""  # clear driver string
363c6dab2a8SThomas Monjalon
3642fc35029SGuduri Prathyusha    # For kernels >= 3.15 driver_override can be used to specify the driver
3652fc35029SGuduri Prathyusha    # for a device rather than relying on the driver to provide a positive
3662fc35029SGuduri Prathyusha    # match of the device.  The existing process of looking up
3672fc35029SGuduri Prathyusha    # the vendor and device ID, adding them to the driver new_id,
3682fc35029SGuduri Prathyusha    # will erroneously bind other devices too which has the additional burden
3692fc35029SGuduri Prathyusha    # of unbinding those devices
370c6dab2a8SThomas Monjalon    if driver in dpdk_drivers:
3712fc35029SGuduri Prathyusha        filename = "/sys/bus/pci/devices/%s/driver_override" % dev_id
3721bb98a90SStephen Hemminger        if exists(filename):
3732fc35029SGuduri Prathyusha            try:
3742fc35029SGuduri Prathyusha                f = open(filename, "w")
37562d3ce60SStephen Hemminger            except OSError as err:
37662d3ce60SStephen Hemminger                print("Error: bind failed for %s - Cannot open %s: %s"
37762d3ce60SStephen Hemminger                      % (dev_id, filename, err), file=sys.stderr)
3782fc35029SGuduri Prathyusha                return
3792fc35029SGuduri Prathyusha            try:
3802fc35029SGuduri Prathyusha                f.write("%s" % driver)
3812fc35029SGuduri Prathyusha                f.close()
38262d3ce60SStephen Hemminger            except OSError as err:
3832fc35029SGuduri Prathyusha                print("Error: bind failed for %s - Cannot write driver %s to "
38462d3ce60SStephen Hemminger                      "PCI ID: %s" % (dev_id, driver, err), file=sys.stderr)
3852fc35029SGuduri Prathyusha                return
3862fc35029SGuduri Prathyusha        # For kernels < 3.15 use new_id to add PCI id's to the driver
3872fc35029SGuduri Prathyusha        else:
388c6dab2a8SThomas Monjalon            filename = "/sys/bus/pci/drivers/%s/new_id" % driver
389c6dab2a8SThomas Monjalon            try:
390c6dab2a8SThomas Monjalon                f = open(filename, "w")
39162d3ce60SStephen Hemminger            except OSError as err:
39262d3ce60SStephen Hemminger                print("Error: bind failed for %s - Cannot open %s: %s"
39362d3ce60SStephen Hemminger                      % (dev_id, filename, err), file=sys.stderr)
394c6dab2a8SThomas Monjalon                return
395c6dab2a8SThomas Monjalon            try:
3968ad08a28SGuduri Prathyusha                # Convert Device and Vendor Id to int to write to new_id
3978ad08a28SGuduri Prathyusha                f.write("%04x %04x" % (int(dev["Vendor"], 16),
3988ad08a28SGuduri Prathyusha                                       int(dev["Device"], 16)))
399c6dab2a8SThomas Monjalon                f.close()
40062d3ce60SStephen Hemminger            except OSError as err:
401c6dab2a8SThomas Monjalon                print("Error: bind failed for %s - Cannot write new PCI ID to "
40262d3ce60SStephen Hemminger                      "driver %s: %s" % (dev_id, driver, err), file=sys.stderr)
403c6dab2a8SThomas Monjalon                return
404c6dab2a8SThomas Monjalon
405c6dab2a8SThomas Monjalon    # do the bind by writing to /sys
406c6dab2a8SThomas Monjalon    filename = "/sys/bus/pci/drivers/%s/bind" % driver
407c6dab2a8SThomas Monjalon    try:
408c6dab2a8SThomas Monjalon        f = open(filename, "a")
40962d3ce60SStephen Hemminger    except OSError as err:
41062d3ce60SStephen Hemminger        print("Error: bind failed for %s - Cannot open %s: %s"
41162d3ce60SStephen Hemminger              % (dev_id, filename, err), file=sys.stderr)
412c6dab2a8SThomas Monjalon        if saved_driver is not None:  # restore any previous driver
413c6dab2a8SThomas Monjalon            bind_one(dev_id, saved_driver, force)
414c6dab2a8SThomas Monjalon        return
415c6dab2a8SThomas Monjalon    try:
416c6dab2a8SThomas Monjalon        f.write(dev_id)
417c6dab2a8SThomas Monjalon        f.close()
41862d3ce60SStephen Hemminger    except OSError as err:
419c6dab2a8SThomas Monjalon        # for some reason, closing dev_id after adding a new PCI ID to new_id
420c6dab2a8SThomas Monjalon        # results in IOError. however, if the device was successfully bound,
421c6dab2a8SThomas Monjalon        # we don't care for any errors and can safely ignore IOError
422c3ce205dSGuduri Prathyusha        tmp = get_pci_device_details(dev_id, True)
423c6dab2a8SThomas Monjalon        if "Driver_str" in tmp and tmp["Driver_str"] == driver:
424c6dab2a8SThomas Monjalon            return
42562d3ce60SStephen Hemminger        print("Error: bind failed for %s - Cannot bind to driver %s: %s"
42662d3ce60SStephen Hemminger              % (dev_id, driver, err), file=sys.stderr)
427c6dab2a8SThomas Monjalon        if saved_driver is not None:  # restore any previous driver
428c6dab2a8SThomas Monjalon            bind_one(dev_id, saved_driver, force)
429c6dab2a8SThomas Monjalon        return
430c6dab2a8SThomas Monjalon
431720b7a05SGuduri Prathyusha    # For kernels > 3.15 driver_override is used to bind a device to a driver.
432720b7a05SGuduri Prathyusha    # Before unbinding it, overwrite driver_override with empty string so that
433720b7a05SGuduri Prathyusha    # the device can be bound to any other driver
434720b7a05SGuduri Prathyusha    filename = "/sys/bus/pci/devices/%s/driver_override" % dev_id
4351bb98a90SStephen Hemminger    if exists(filename):
436720b7a05SGuduri Prathyusha        try:
437720b7a05SGuduri Prathyusha            f = open(filename, "w")
43862d3ce60SStephen Hemminger        except OSError as err:
43962d3ce60SStephen Hemminger            sys.exit("Error: unbind failed for %s - Cannot open %s: %s"
44062d3ce60SStephen Hemminger                     % (dev_id, filename, err))
441720b7a05SGuduri Prathyusha        try:
442720b7a05SGuduri Prathyusha            f.write("\00")
443720b7a05SGuduri Prathyusha            f.close()
44462d3ce60SStephen Hemminger        except OSError as err:
44562d3ce60SStephen Hemminger            sys.exit("Error: unbind failed for %s - Cannot write %s: %s"
44662d3ce60SStephen Hemminger                     % (dev_id, filename, err))
447720b7a05SGuduri Prathyusha
448c6dab2a8SThomas Monjalon
449c6dab2a8SThomas Monjalondef unbind_all(dev_list, force=False):
450c6dab2a8SThomas Monjalon    """Unbind method, takes a list of device locations"""
451657c7133SFerruh Yigit
452657c7133SFerruh Yigit    if dev_list[0] == "dpdk":
453657c7133SFerruh Yigit        for d in devices.keys():
454657c7133SFerruh Yigit            if "Driver_str" in devices[d]:
455657c7133SFerruh Yigit                if devices[d]["Driver_str"] in dpdk_drivers:
456657c7133SFerruh Yigit                    unbind_one(devices[d]["Slot"], force)
457657c7133SFerruh Yigit        return
458657c7133SFerruh Yigit
45915f6aac7SAnatoly Burakov    try:
460c6dab2a8SThomas Monjalon        dev_list = map(dev_id_from_dev_name, dev_list)
46115f6aac7SAnatoly Burakov    except ValueError as ex:
46215f6aac7SAnatoly Burakov        print(ex)
46315f6aac7SAnatoly Burakov        sys.exit(1)
46415f6aac7SAnatoly Burakov
465c6dab2a8SThomas Monjalon    for d in dev_list:
466c6dab2a8SThomas Monjalon        unbind_one(d, force)
467c6dab2a8SThomas Monjalon
468c6dab2a8SThomas Monjalon
469c6dab2a8SThomas Monjalondef bind_all(dev_list, driver, force=False):
470c6dab2a8SThomas Monjalon    """Bind method, takes a list of device locations"""
471c6dab2a8SThomas Monjalon    global devices
472c6dab2a8SThomas Monjalon
47315f6aac7SAnatoly Burakov    # a common user error is to forget to specify the driver the devices need to
47415f6aac7SAnatoly Burakov    # be bound to. check if the driver is a valid device, and if it is, show
47515f6aac7SAnatoly Burakov    # a meaningful error.
47615f6aac7SAnatoly Burakov    try:
47715f6aac7SAnatoly Burakov        dev_id_from_dev_name(driver)
47815f6aac7SAnatoly Burakov        # if we've made it this far, this means that the "driver" was a valid
47915f6aac7SAnatoly Burakov        # device string, so it's probably not a valid driver name.
48062d3ce60SStephen Hemminger        sys.exit("Error: Driver '%s' does not look like a valid driver. "
48115f6aac7SAnatoly Burakov                 "Did you forget to specify the driver to bind devices to?" % driver)
48215f6aac7SAnatoly Burakov    except ValueError:
48315f6aac7SAnatoly Burakov        # driver generated error - it's not a valid device ID, so all is well
48415f6aac7SAnatoly Burakov        pass
48515f6aac7SAnatoly Burakov
486681a6728SAnatoly Burakov    # check if we're attempting to bind to a driver that isn't loaded
48743623124SPavan Nikhilesh    if not module_is_loaded(driver.replace('-', '_')):
488681a6728SAnatoly Burakov        sys.exit("Error: Driver '%s' is not loaded." % driver)
489681a6728SAnatoly Burakov
49015f6aac7SAnatoly Burakov    try:
491c6dab2a8SThomas Monjalon        dev_list = map(dev_id_from_dev_name, dev_list)
49215f6aac7SAnatoly Burakov    except ValueError as ex:
49315f6aac7SAnatoly Burakov        sys.exit(ex)
494c6dab2a8SThomas Monjalon
495c6dab2a8SThomas Monjalon    for d in dev_list:
496c6dab2a8SThomas Monjalon        bind_one(d, driver, force)
497c6dab2a8SThomas Monjalon
498e4839614SPavel Shirshov    # For kernels < 3.15 when binding devices to a generic driver
4992fc35029SGuduri Prathyusha    # (i.e. one that doesn't have a PCI ID table) using new_id, some devices
5002fc35029SGuduri Prathyusha    # that are not bound to any other driver could be bound even if no one has
5012fc35029SGuduri Prathyusha    # asked them to. hence, we check the list of drivers again, and see if
5022fc35029SGuduri Prathyusha    # some of the previously-unbound devices were erroneously bound.
5031bb98a90SStephen Hemminger    if not exists("/sys/bus/pci/devices/%s/driver_override" % d):
504c6dab2a8SThomas Monjalon        for d in devices.keys():
505c6dab2a8SThomas Monjalon            # skip devices that were already bound or that we know should be bound
506c6dab2a8SThomas Monjalon            if "Driver_str" in devices[d] or d in dev_list:
507c6dab2a8SThomas Monjalon                continue
508c6dab2a8SThomas Monjalon
509c6dab2a8SThomas Monjalon            # update information about this device
51062d3ce60SStephen Hemminger            devices[d] = dict(devices[d].items()
51162d3ce60SStephen Hemminger                              + get_pci_device_details(d, True).items())
512c6dab2a8SThomas Monjalon
513c6dab2a8SThomas Monjalon            # check if updated information indicates that the device was bound
514c6dab2a8SThomas Monjalon            if "Driver_str" in devices[d]:
515c6dab2a8SThomas Monjalon                unbind_one(d, force)
516c6dab2a8SThomas Monjalon
517c6dab2a8SThomas Monjalon
518c6dab2a8SThomas Monjalondef display_devices(title, dev_list, extra_params=None):
519c6dab2a8SThomas Monjalon    '''Displays to the user the details of a list of devices given in
520c6dab2a8SThomas Monjalon    "dev_list". The "extra_params" parameter, if given, should contain a string
521c6dab2a8SThomas Monjalon     with %()s fields in it for replacement by the named fields in each
522c6dab2a8SThomas Monjalon     device's dictionary.'''
523c6dab2a8SThomas Monjalon    strings = []  # this holds the strings to print. We sort before printing
524c6dab2a8SThomas Monjalon    print("\n%s" % title)
525c6dab2a8SThomas Monjalon    print("=" * len(title))
526d58360c6SStephen Hemminger    if not dev_list:
527c6dab2a8SThomas Monjalon        strings.append("<none>")
528c6dab2a8SThomas Monjalon    else:
529c6dab2a8SThomas Monjalon        for dev in dev_list:
530c6dab2a8SThomas Monjalon            if extra_params is not None:
531c3ce205dSGuduri Prathyusha                strings.append("%s '%s %s' %s" % (dev["Slot"],
532c6dab2a8SThomas Monjalon                                                  dev["Device_str"],
533c3ce205dSGuduri Prathyusha                                                  dev["Device"],
534c6dab2a8SThomas Monjalon                                                  extra_params % dev))
535c6dab2a8SThomas Monjalon            else:
536c6dab2a8SThomas Monjalon                strings.append("%s '%s'" % (dev["Slot"], dev["Device_str"]))
537c6dab2a8SThomas Monjalon    # sort before printing, so that the entries appear in PCI order
538c6dab2a8SThomas Monjalon    strings.sort()
539c6dab2a8SThomas Monjalon    print("\n".join(strings))  # print one per line
540c6dab2a8SThomas Monjalon
54162d3ce60SStephen Hemminger
54236f66d1cSBruce Richardsondef show_device_status(devices_type, device_name, if_field=False):
543c6dab2a8SThomas Monjalon    global dpdk_drivers
544c6dab2a8SThomas Monjalon    kernel_drv = []
545c6dab2a8SThomas Monjalon    dpdk_drv = []
546c6dab2a8SThomas Monjalon    no_drv = []
547c6dab2a8SThomas Monjalon
548c6dab2a8SThomas Monjalon    # split our list of network devices into the three categories above
549c6dab2a8SThomas Monjalon    for d in devices.keys():
5508ad08a28SGuduri Prathyusha        if device_type_match(devices[d], devices_type):
551c6dab2a8SThomas Monjalon            if not has_driver(d):
552c6dab2a8SThomas Monjalon                no_drv.append(devices[d])
553c6dab2a8SThomas Monjalon                continue
554c6dab2a8SThomas Monjalon            if devices[d]["Driver_str"] in dpdk_drivers:
555c6dab2a8SThomas Monjalon                dpdk_drv.append(devices[d])
556c6dab2a8SThomas Monjalon            else:
557c6dab2a8SThomas Monjalon                kernel_drv.append(devices[d])
558c6dab2a8SThomas Monjalon
559109cb989SAnatoly Burakov    n_devs = len(dpdk_drv) + len(kernel_drv) + len(no_drv)
560109cb989SAnatoly Burakov
561109cb989SAnatoly Burakov    # don't bother displaying anything if there are no devices
562109cb989SAnatoly Burakov    if n_devs == 0:
563109cb989SAnatoly Burakov        msg = "No '%s' devices detected" % device_name
564109cb989SAnatoly Burakov        print("")
565109cb989SAnatoly Burakov        print(msg)
566109cb989SAnatoly Burakov        print("".join('=' * len(msg)))
567109cb989SAnatoly Burakov        return
568109cb989SAnatoly Burakov
569c6dab2a8SThomas Monjalon    # print each category separately, so we can clearly see what's used by DPDK
570d58360c6SStephen Hemminger    if dpdk_drv:
5718ad08a28SGuduri Prathyusha        display_devices("%s devices using DPDK-compatible driver" % device_name,
5728ad08a28SGuduri Prathyusha                        dpdk_drv, "drv=%(Driver_str)s unused=%(Module_str)s")
573d58360c6SStephen Hemminger    if kernel_drv:
57436f66d1cSBruce Richardson        if_text = ""
57536f66d1cSBruce Richardson        if if_field:
57636f66d1cSBruce Richardson            if_text = "if=%(Interface)s "
577c7dd412bSGuduri Prathyusha        display_devices("%s devices using kernel driver" % device_name, kernel_drv,
57836f66d1cSBruce Richardson                        if_text + "drv=%(Driver_str)s "
579c6dab2a8SThomas Monjalon                        "unused=%(Module_str)s %(Active)s")
580d58360c6SStephen Hemminger    if no_drv:
5818ad08a28SGuduri Prathyusha        display_devices("Other %s devices" % device_name, no_drv,
5828ad08a28SGuduri Prathyusha                        "unused=%(Module_str)s")
583c6dab2a8SThomas Monjalon
58462d3ce60SStephen Hemminger
585c7dd412bSGuduri Prathyushadef show_status():
586c7dd412bSGuduri Prathyusha    '''Function called when the script is passed the "--status" option.
587c7dd412bSGuduri Prathyusha    Displays to the user what devices are bound to the igb_uio driver, the
588c7dd412bSGuduri Prathyusha    kernel driver or to no driver'''
589c6dab2a8SThomas Monjalon
5900a3f92cdSStephen Hemminger    if status_dev in ["net", "all"]:
59136f66d1cSBruce Richardson        show_device_status(network_devices, "Network", if_field=True)
592b153c00bSFerruh Yigit
5930a3f92cdSStephen Hemminger    if status_dev in ["baseband", "all"]:
59407488e29SNicolas Chautru        show_device_status(baseband_devices, "Baseband")
59507488e29SNicolas Chautru
5960a3f92cdSStephen Hemminger    if status_dev in ["crypto", "all"]:
597c7dd412bSGuduri Prathyusha        show_device_status(crypto_devices, "Crypto")
598b153c00bSFerruh Yigit
5999afeef14SKevin Laatz    if status_dev in ["dma", "all"]:
6009afeef14SKevin Laatz        show_device_status(dma_devices, "DMA")
6019afeef14SKevin Laatz
6020a3f92cdSStephen Hemminger    if status_dev in ["event", "all"]:
60332a02dbfSGuduri Prathyusha        show_device_status(eventdev_devices, "Eventdev")
604b153c00bSFerruh Yigit
6050a3f92cdSStephen Hemminger    if status_dev in ["mempool", "all"]:
60680a1858dSGuduri Prathyusha        show_device_status(mempool_devices, "Mempool")
607c6dab2a8SThomas Monjalon
6080a3f92cdSStephen Hemminger    if status_dev in ["compress", "all"]:
6099d35895eSSunila Sahu        show_device_status(compress_devices, "Compress")
6109d35895eSSunila Sahu
6110a3f92cdSStephen Hemminger    if status_dev in ["misc", "all"]:
61212d4777aSBruce Richardson        show_device_status(misc_devices, "Misc (rawdev)")
6139d35895eSSunila Sahu
6140a3f92cdSStephen Hemminger    if status_dev in ["regex", "all"]:
61509f84c9aSGuy Kaneti        show_device_status(regex_devices, "Regex")
61609f84c9aSGuy Kaneti
617781eafc9SBruce Richardson
618781eafc9SBruce Richardsondef pci_glob(arg):
619781eafc9SBruce Richardson    '''Returns a list containing either:
620781eafc9SBruce Richardson    * List of PCI B:D:F matching arg, using shell wildcards e.g. 80:04.*
621781eafc9SBruce Richardson    * Only the passed arg if matching list is empty'''
622781eafc9SBruce Richardson    sysfs_path = "/sys/bus/pci/devices"
623781eafc9SBruce Richardson    for _glob in [arg, '0000:' + arg]:
624781eafc9SBruce Richardson        paths = [basename(path) for path in glob(path_join(sysfs_path, _glob))]
625781eafc9SBruce Richardson        if paths:
626781eafc9SBruce Richardson            return paths
627781eafc9SBruce Richardson    return [arg]
628781eafc9SBruce Richardson
629781eafc9SBruce Richardson
630c6dab2a8SThomas Monjalondef parse_args():
631c6dab2a8SThomas Monjalon    '''Parses the command-line arguments given by the user and takes the
632c6dab2a8SThomas Monjalon    appropriate action for each'''
633c6dab2a8SThomas Monjalon    global b_flag
634c6dab2a8SThomas Monjalon    global status_flag
635b153c00bSFerruh Yigit    global status_dev
636c6dab2a8SThomas Monjalon    global force_flag
637c6dab2a8SThomas Monjalon    global args
638c6dab2a8SThomas Monjalon
63981255f27SStephen Hemminger    parser = argparse.ArgumentParser(
64081255f27SStephen Hemminger        description='Utility to bind and unbind devices from Linux kernel',
64181255f27SStephen Hemminger        formatter_class=argparse.RawDescriptionHelpFormatter,
64281255f27SStephen Hemminger        epilog="""
64381255f27SStephen HemmingerExamples:
64481255f27SStephen Hemminger---------
645c6dab2a8SThomas Monjalon
64681255f27SStephen HemmingerTo display current device status:
64781255f27SStephen Hemminger        %(prog)s --status
64881255f27SStephen Hemminger
64981255f27SStephen HemmingerTo display current network device status:
65081255f27SStephen Hemminger        %(prog)s --status-dev net
65181255f27SStephen Hemminger
65281255f27SStephen HemmingerTo bind eth1 from the current driver and move to use vfio-pci
65381255f27SStephen Hemminger        %(prog)s --bind=vfio-pci eth1
65481255f27SStephen Hemminger
65581255f27SStephen HemmingerTo unbind 0000:01:00.0 from using any driver
65681255f27SStephen Hemminger        %(prog)s -u 0000:01:00.0
65781255f27SStephen Hemminger
65881255f27SStephen HemmingerTo bind 0000:02:00.0 and 0000:02:00.1 to the ixgbe kernel driver
65981255f27SStephen Hemminger        %(prog)s -b ixgbe 02:00.0 02:00.1
66081255f27SStephen Hemminger""")
66181255f27SStephen Hemminger
66281255f27SStephen Hemminger    parser.add_argument(
66381255f27SStephen Hemminger        '-s',
66481255f27SStephen Hemminger        '--status',
66581255f27SStephen Hemminger        action='store_true',
66681255f27SStephen Hemminger        help="Print the current status of all known devices.")
66781255f27SStephen Hemminger    parser.add_argument(
66881255f27SStephen Hemminger        '--status-dev',
66981255f27SStephen Hemminger        help="Print the status of given device group.",
6709afeef14SKevin Laatz        choices=['baseband', 'compress', 'crypto', 'dma', 'event',
671f32fed83SBruce Richardson                 'mempool', 'misc', 'net', 'regex'])
67281255f27SStephen Hemminger    bind_group = parser.add_mutually_exclusive_group()
67381255f27SStephen Hemminger    bind_group.add_argument(
67481255f27SStephen Hemminger        '-b',
67581255f27SStephen Hemminger        '--bind',
67681255f27SStephen Hemminger        metavar='DRIVER',
67781255f27SStephen Hemminger        help="Select the driver to use or \"none\" to unbind the device")
67881255f27SStephen Hemminger    bind_group.add_argument(
67981255f27SStephen Hemminger        '-u',
68081255f27SStephen Hemminger        '--unbind',
68181255f27SStephen Hemminger        action='store_true',
68281255f27SStephen Hemminger        help="Unbind a device (equivalent to \"-b none\")")
68381255f27SStephen Hemminger    parser.add_argument(
68481255f27SStephen Hemminger        '--force',
68581255f27SStephen Hemminger        action='store_true',
68681255f27SStephen Hemminger        help="""
68781255f27SStephen HemmingerOverride restriction on binding devices in use by Linux"
68881255f27SStephen HemmingerWARNING: This can lead to loss of network connection and should be used with caution.
68981255f27SStephen Hemminger""")
69081255f27SStephen Hemminger    parser.add_argument(
69181255f27SStephen Hemminger        'devices',
69281255f27SStephen Hemminger        metavar='DEVICE',
69381255f27SStephen Hemminger        nargs='*',
69481255f27SStephen Hemminger        help="""
69581255f27SStephen HemmingerDevice specified as PCI "domain:bus:slot.func" syntax or "bus:slot.func" syntax.
69681255f27SStephen HemmingerFor devices bound to Linux kernel drivers, they may be referred to by interface name.
69781255f27SStephen Hemminger""")
69881255f27SStephen Hemminger
69981255f27SStephen Hemminger    opt = parser.parse_args()
70081255f27SStephen Hemminger
70181255f27SStephen Hemminger    if opt.status_dev:
702b153c00bSFerruh Yigit        status_flag = True
70381255f27SStephen Hemminger        status_dev = opt.status_dev
70481255f27SStephen Hemminger    if opt.status:
705c6dab2a8SThomas Monjalon        status_flag = True
706b153c00bSFerruh Yigit        status_dev = "all"
70781255f27SStephen Hemminger    if opt.force:
708c6dab2a8SThomas Monjalon        force_flag = True
70981255f27SStephen Hemminger    if opt.bind:
71081255f27SStephen Hemminger        b_flag = opt.bind
71181255f27SStephen Hemminger    elif opt.unbind:
712c6dab2a8SThomas Monjalon        b_flag = "none"
71381255f27SStephen Hemminger    args = opt.devices
71481255f27SStephen Hemminger
71581255f27SStephen Hemminger    if not b_flag and not status_flag:
71681255f27SStephen Hemminger        print("Error: No action specified for devices. "
71781255f27SStephen Hemminger              "Please give a --bind, --ubind or --status option",
71881255f27SStephen Hemminger              file=sys.stderr)
71981255f27SStephen Hemminger        parser.print_usage()
72081255f27SStephen Hemminger        sys.exit(1)
72181255f27SStephen Hemminger
72281255f27SStephen Hemminger    if b_flag and not args:
72381255f27SStephen Hemminger        print("Error: No devices specified.", file=sys.stderr)
72481255f27SStephen Hemminger        parser.print_usage()
72581255f27SStephen Hemminger        sys.exit(1)
726c6dab2a8SThomas Monjalon
727781eafc9SBruce Richardson    # resolve any PCI globs in the args
728781eafc9SBruce Richardson    new_args = []
729781eafc9SBruce Richardson    for arg in args:
730781eafc9SBruce Richardson        new_args.extend(pci_glob(arg))
731781eafc9SBruce Richardson    args = new_args
732c6dab2a8SThomas Monjalon
73362d3ce60SStephen Hemminger
734c6dab2a8SThomas Monjalondef do_arg_actions():
735c6dab2a8SThomas Monjalon    '''do the actual action requested by the user'''
736c6dab2a8SThomas Monjalon    global b_flag
737c6dab2a8SThomas Monjalon    global status_flag
738c6dab2a8SThomas Monjalon    global force_flag
739c6dab2a8SThomas Monjalon    global args
740c6dab2a8SThomas Monjalon
7410a3f92cdSStephen Hemminger    if b_flag in ["none", "None"]:
742c6dab2a8SThomas Monjalon        unbind_all(args, force_flag)
743c6dab2a8SThomas Monjalon    elif b_flag is not None:
744c6dab2a8SThomas Monjalon        bind_all(args, b_flag, force_flag)
745c6dab2a8SThomas Monjalon    if status_flag:
746c6dab2a8SThomas Monjalon        if b_flag is not None:
747ea9f00f7SGuduri Prathyusha            clear_data()
7488ad08a28SGuduri Prathyusha            # refresh if we have changed anything
7498ad08a28SGuduri Prathyusha            get_device_details(network_devices)
75007488e29SNicolas Chautru            get_device_details(baseband_devices)
7518ad08a28SGuduri Prathyusha            get_device_details(crypto_devices)
7529afeef14SKevin Laatz            get_device_details(dma_devices)
75332a02dbfSGuduri Prathyusha            get_device_details(eventdev_devices)
75480a1858dSGuduri Prathyusha            get_device_details(mempool_devices)
7559d35895eSSunila Sahu            get_device_details(compress_devices)
75609f84c9aSGuy Kaneti            get_device_details(regex_devices)
75712d4777aSBruce Richardson            get_device_details(misc_devices)
758c6dab2a8SThomas Monjalon        show_status()
759c6dab2a8SThomas Monjalon
760c6dab2a8SThomas Monjalon
761c6dab2a8SThomas Monjalondef main():
762c6dab2a8SThomas Monjalon    '''program main function'''
7631a5a9cb3SAnatoly Burakov    # check if lspci is installed, suppress any output
7641a5a9cb3SAnatoly Burakov    with open(os.devnull, 'w') as devnull:
7651a5a9cb3SAnatoly Burakov        ret = subprocess.call(['which', 'lspci'],
7661a5a9cb3SAnatoly Burakov                              stdout=devnull, stderr=devnull)
7671a5a9cb3SAnatoly Burakov        if ret != 0:
7682804529fSAnatoly Burakov            sys.exit("'lspci' not found - please install 'pciutils'")
769c6dab2a8SThomas Monjalon    parse_args()
770c6dab2a8SThomas Monjalon    check_modules()
771ea9f00f7SGuduri Prathyusha    clear_data()
7728ad08a28SGuduri Prathyusha    get_device_details(network_devices)
77307488e29SNicolas Chautru    get_device_details(baseband_devices)
7748ad08a28SGuduri Prathyusha    get_device_details(crypto_devices)
7759afeef14SKevin Laatz    get_device_details(dma_devices)
77632a02dbfSGuduri Prathyusha    get_device_details(eventdev_devices)
77780a1858dSGuduri Prathyusha    get_device_details(mempool_devices)
7789d35895eSSunila Sahu    get_device_details(compress_devices)
77909f84c9aSGuy Kaneti    get_device_details(regex_devices)
78012d4777aSBruce Richardson    get_device_details(misc_devices)
781c6dab2a8SThomas Monjalon    do_arg_actions()
782c6dab2a8SThomas Monjalon
78362d3ce60SStephen Hemminger
784c6dab2a8SThomas Monjalonif __name__ == "__main__":
785c6dab2a8SThomas Monjalon    main()
786