All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jerin Jacob <jerin.jacob@caviumnetworks.com>
To: dev@dpdk.org
Cc: thomas.monjalon@6wind.com, ferruh.yigit@intel.com,
	gprathyusha@caviumnetworks.com,
	Jerin Jacob <jerin.jacob@caviumnetworks.com>
Subject: [PATCH 4/7] usertools: use optimized driver override scheme to bind
Date: Wed, 22 Mar 2017 19:41:29 +0530	[thread overview]
Message-ID: <1490191892-10396-5-git-send-email-jerin.jacob@caviumnetworks.com> (raw)
In-Reply-To: <1490191892-10396-1-git-send-email-jerin.jacob@caviumnetworks.com>

From: Guduri Prathyusha <gprathyusha@caviumnetworks.com>

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 <gprathyusha@caviumnetworks.com>
Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
---
 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 9beadde..4dc6a66 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.5.5

  parent reply	other threads:[~2017-03-22 14:12 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-22 14:11 [PATCH 0/7] dpdk-devbind.py refactor Jerin Jacob
2017-03-22 14:11 ` [PATCH 1/7] usertools: refactor the get NIC and crypto details Jerin Jacob
2017-03-22 14:11 ` [PATCH 2/7] usertools: refactor the show status function Jerin Jacob
2017-03-22 14:11 ` [PATCH 3/7] usertools: optimize lspci invocation Jerin Jacob
2017-03-22 14:11 ` Jerin Jacob [this message]
2017-03-22 14:11 ` [PATCH 5/7] usertools: define DPDK PCI functional device Jerin Jacob
2017-03-22 14:11 ` [PATCH 6/7] usertools: add eventdev " Jerin Jacob
2017-03-22 14:11 ` [PATCH 7/7] usertools: add mempool " Jerin Jacob
2017-04-25  9:30 ` [PATCH 0/7] dpdk-devbind.py refactor Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1490191892-10396-5-git-send-email-jerin.jacob@caviumnetworks.com \
    --to=jerin.jacob@caviumnetworks.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=gprathyusha@caviumnetworks.com \
    --cc=thomas.monjalon@6wind.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.