From 2fc3502935700243d9a6d903166e6fd11e429843 Mon Sep 17 00:00:00 2001 From: Guduri Prathyusha Date: Wed, 22 Mar 2017 19:41:29 +0530 Subject: [PATCH] usertools: use optimized driver override scheme to bind The current device bind model uses /sys/bus/pci/driver/new_id scheme to bind devices to the driver. This scheme has following operations to bind a device to the driver. 1) Write device ID and vendor ID to /sys/bus/pci/driver/new_id 2) Write PCI BDF number to /sys/bus/pci/driver/bind 3) On step (1), _All_ the devices that match the device ID and vendor ID get bound to the driver 4) Except for requested devices, Unbind the remaining devices In kernels >= 3.15, An alternative scheme driver_override can be used to bind a device to driver.This scheme has following operations to bind a device to driver. 1) Write driver to /sys/bus/pci/device/driver_override 2) Write PCI BDF number to /sys/bus/pci/driver/bind This script detects the presence of /sys/bus/pci/device/driver_override, if available use optimized bind scheme to bind it Signed-off-by: Guduri Prathyusha Signed-off-by: Jerin Jacob --- usertools/dpdk-devbind.py | 109 ++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 34 deletions(-) diff --git a/usertools/dpdk-devbind.py b/usertools/dpdk-devbind.py index 9beadde4ed..4dc6a66570 100755 --- a/usertools/dpdk-devbind.py +++ b/usertools/dpdk-devbind.py @@ -355,6 +355,25 @@ def unbind_one(dev_id, force): "Skipping unbind" % (dev_id)) return + # For kernels > 3.15 driver_override is used to bind a device to a driver. + # Before unbinding it, overwrite driver_override with empty string so that + # the device can be bound to any other driver + filename = "/sys/bus/pci/devices/%s/driver_override" % dev_id + if os.path.exists(filename): + try: + f = open(filename, "w") + except: + print("Error: unbind failed for %s - Cannot open %s" + % (dev_id, filename)) + sys.exit(1) + try: + f.write("\00") + f.close() + except: + print("Error: unbind failed for %s - Cannot open %s" + % (dev_id, filename)) + sys.exit(1) + # write to /sys to unbind filename = "/sys/bus/pci/drivers/%s/unbind" % dev["Driver_str"] try: @@ -390,22 +409,44 @@ def bind_one(dev_id, driver, force): unbind_one(dev_id, force) dev["Driver_str"] = "" # clear driver string - # if we are binding to one of DPDK drivers, add PCI id's to that driver + # For kernels >= 3.15 driver_override can be used to specify the driver + # for a device rather than relying on the driver to provide a positive + # match of the device. The existing process of looking up + # the vendor and device ID, adding them to the driver new_id, + # will erroneously bind other devices too which has the additional burden + # of unbinding those devices if driver in dpdk_drivers: - filename = "/sys/bus/pci/drivers/%s/new_id" % driver - try: - f = open(filename, "w") - except: - print("Error: bind failed for %s - Cannot open %s" - % (dev_id, filename)) - return - try: - f.write("%04x %04x" % (dev["Vendor"], dev["Device"])) - f.close() - except: - print("Error: bind failed for %s - Cannot write new PCI ID to " - "driver %s" % (dev_id, driver)) - return + filename = "/sys/bus/pci/devices/%s/driver_override" % dev_id + if os.path.exists(filename): + try: + f = open(filename, "w") + except: + print("Error: bind failed for %s - Cannot open %s" + % (dev_id, filename)) + return + try: + f.write("%s" % driver) + f.close() + except: + print("Error: bind failed for %s - Cannot write driver %s to " + "PCI ID " % (dev_id, driver)) + return + # For kernels < 3.15 use new_id to add PCI id's to the driver + else: + filename = "/sys/bus/pci/drivers/%s/new_id" % driver + try: + f = open(filename, "w") + except: + print("Error: bind failed for %s - Cannot open %s" + % (dev_id, filename)) + return + try: + f.write("%04x %04x" % (dev["Vendor"], dev["Device"])) + f.close() + except: + print("Error: bind failed for %s - Cannot write new PCI ID to " + "driver %s" % (dev_id, driver)) + return # do the bind by writing to /sys filename = "/sys/bus/pci/drivers/%s/bind" % driver @@ -450,23 +491,24 @@ def bind_all(dev_list, driver, force=False): for d in dev_list: bind_one(d, driver, force) - # when binding devices to a generic driver (i.e. one that doesn't have a - # PCI ID table), some devices that are not bound to any other driver could - # be bound even if no one has asked them to. hence, we check the list of - # drivers again, and see if some of the previously-unbound devices were - # erroneously bound. - for d in devices.keys(): - # skip devices that were already bound or that we know should be bound - if "Driver_str" in devices[d] or d in dev_list: - continue + # For kenels < 3.15 when binding devices to a generic driver + # (i.e. one that doesn't have a PCI ID table) using new_id, some devices + # that are not bound to any other driver could be bound even if no one has + # asked them to. hence, we check the list of drivers again, and see if + # some of the previously-unbound devices were erroneously bound. + if not os.path.exists("/sys/bus/pci/devices/%s/driver_override" % d): + for d in devices.keys(): + # skip devices that were already bound or that we know should be bound + if "Driver_str" in devices[d] or d in dev_list: + continue - # update information about this device - devices[d] = dict(devices[d].items() + - get_pci_device_details(d, True).items()) + # update information about this device + devices[d] = dict(devices[d].items() + + get_pci_device_details(d, True).items()) - # check if updated information indicates that the device was bound - if "Driver_str" in devices[d]: - unbind_one(d, force) + # check if updated information indicates that the device was bound + if "Driver_str" in devices[d]: + unbind_one(d, force) def display_devices(title, dev_list, extra_params=None): @@ -510,13 +552,12 @@ def show_device_status(devices_type, device_name): kernel_drv.append(devices[d]) # print each category separately, so we can clearly see what's used by DPDK - display_devices("%s devices using DPDK-compatible driver" % device_name, - dpdk_drv, "drv=%(Driver_str)s unused=%(Module_str)s") + display_devices("%s devices using DPDK-compatible driver" % device_name, dpdk_drv, + "drv=%(Driver_str)s unused=%(Module_str)s") display_devices("%s devices using kernel driver" % device_name, kernel_drv, "if=%(Interface)s drv=%(Driver_str)s " "unused=%(Module_str)s %(Active)s") - display_devices("Other %s devices" % device_name, no_drv, - "unused=%(Module_str)s") + display_devices("Other %s devices" % device_name, no_drv, "unused=%(Module_str)s") def show_status(): '''Function called when the script is passed the "--status" option. -- 2.20.1