kernel_AsyncDriverProbe: add test for asynchronous driver probing

We need to make sure asynchronous driver probing works well in our
kernels; this test will ensure that.

The test requires test_async_driver_probe.ko module be available, we'll
ensure that it is there with kernel_ConfigVerify test.

BUG=chromium:415343
TEST=tested on Squawks after booting image with test module enabled
CQ-DEPEND=CL:219107

Change-Id: Ifc775e0b6e85e11351a5f10e54f57c03573a7714
Signed-off-by: Dmitry Torokhov <dtor@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/219393
Reviewed-by: Olof Johansson <olofj@chromium.org>
diff --git a/client/site_tests/kernel_AsyncDriverProbe/control b/client/site_tests/kernel_AsyncDriverProbe/control
new file mode 100644
index 0000000..dd06392
--- /dev/null
+++ b/client/site_tests/kernel_AsyncDriverProbe/control
@@ -0,0 +1,25 @@
+# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+NAME = "kernel_AsyncDriverProbe"
+AUTHOR = "The Chromium OS Authors"
+PURPOSE = "Verify kernel correctly implements asynchronous driver probing"
+CRITERIA = """
+   Fails if device registration for devices controlled by drivers requesting
+   asynchronous probing takes too long.
+"""
+TIME = "SHORT"
+SUITE = "kernel_per-build_regression"
+TEST_CATEGORY = "Functional"
+TEST_CLASS = "kernel"
+TEST_TYPE = "client"
+
+DOC = """
+    Checks that the kernel correctly implements asynchronous probing for
+    drivers that request it by checking time needed to execute
+    platform_device_register() and platform_driver_register() calls with
+    driver that takes 10 secs to probe device.
+"""
+
+job.run_test('kernel_AsyncDriverProbe')
diff --git a/client/site_tests/kernel_AsyncDriverProbe/kernel_AsyncDriverProbe.py b/client/site_tests/kernel_AsyncDriverProbe/kernel_AsyncDriverProbe.py
new file mode 100644
index 0000000..d386e79
--- /dev/null
+++ b/client/site_tests/kernel_AsyncDriverProbe/kernel_AsyncDriverProbe.py
@@ -0,0 +1,64 @@
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import subprocess
+from autotest_lib.client.bin import test
+from autotest_lib.client.common_lib import error
+
+class kernel_AsyncDriverProbe(test.test):
+    """
+    Handle checking asynchronous device probing.
+    """
+    version = 1
+
+    def module_loaded(self, module):
+        """
+        Detect if the given module is already loaded in the kernel.
+
+        @param module: name of module to check
+        """
+        module = module.replace('-', '_')
+        match = "%s " % (module)
+        for line in open("/proc/modules"):
+            if line.startswith(match):
+                return True
+        return False
+
+    def rmmod(self, module):
+        """
+        Unload a module if it is already loaded in the kernel.
+
+        @param module: name of module to unload
+        """
+        if self.module_loaded(module):
+            subprocess.call(["rmmod", module])
+
+    def run_once(self):
+        """
+        Try loading the test module. It will time registration for
+        synchronous and asynchronous cases and will fail to load if
+        timing is off.
+        """
+
+        module = "test_async_driver_probe"
+
+        # Start from a clean slate.
+        self.rmmod(module)
+
+        exit_code = subprocess.call(["modprobe", "-n", "-q", module])
+        if exit_code:
+            raise error.TestNAError(
+                "%s.ko module does not seem to be available "
+                "(modprobe rc=%s); skipping async probe test" %
+                (module, exit_code))
+
+        # Try loading the module. If it loads successfully test passes.
+        subprocess.call(["modprobe", module])
+        loaded = self.module_loaded(module)
+
+        # Clean up after ourselves
+        self.rmmod(module)
+
+        if not loaded:
+            raise error.TestFail("Test module failed to load")