<div dir="ltr"><div dir="ltr"><div>From: Harald Freudenberger <<a href="mailto:freude@linux.ibm.com">freude@linux.ibm.com</a>></div><div><br></div><div>BugLink: <a href="http://bugs.launchpad.net/bugs/1799184">http://bugs.launchpad.net/bugs/1799184</a></div><div><br></div><div>The current AP bus, AP devices and AP device drivers implementation</div><div>uses a clearly defined mapping for binding AP devices to AP device</div><div>drivers. So for example a CEX6C queue will always be bound to the</div><div>cex4queue device driver.</div><div><br></div><div>The Linux Device Driver model has no sensitivity for more than one</div><div>device driver eligible for one device type. If there exist more than</div><div>one drivers matching to the device type, simple all drivers are tried</div><div>consecutively.  There is no way to determine and influence the probing</div><div>order of the drivers.</div><div><br></div><div>With KVM there is a need to provide additional device drivers matching</div><div>to the very same type of AP devices. With a simple implementation the</div><div>KVM drivers run in competition to the regular drivers. Whichever</div><div>'wins' a device depends on build order and implementation details</div><div>within the common Linux Device Driver Model and is not</div><div>deterministic. However, a userspace process could figure out which</div><div>device should be bound to which driver and sort out the correct</div><div>binding by manipulating attributes in the sysfs.</div><div><br></div><div>If for security reasons a AP device must not get bound to the 'wrong'</div><div>device driver the sorting out has to be done within the Linux kernel</div><div>by the AP bus code. This patch modifies the behavior of the AP bus</div><div>for probing drivers for devices in a way that two sets of drivers are</div><div>usable. Two new bitmasks 'apmask' and 'aqmask' are used to mark a</div><div>subset of the APQN range for 'usable by the ap bus and the default</div><div>drivers' or 'not usable by the default drivers and thus available for</div><div>alternate drivers like vfio-xxx'. So an APQN which is addressed by</div><div>this masking only the default drivers will be probed. In contrary an</div><div>APQN which is not addressed by the masks will never be probed and</div><div>bound to default drivers but onny to alternate drivers.</div><div><br></div><div>Eventually the two masks give a way to divide the range of APQNs into</div><div>two pools: one pool of APQNs used by the AP bus and the default</div><div>drivers and thus via zcrypt drivers available to the userspace of the</div><div>system. And another pool where no zcrypt drivers are bound to and</div><div>which can be used by alternate drivers (like vfio-xxx) for their</div><div>needs. This division is hot-plug save and makes sure a APQN assigned</div><div>to an alternate driver is at no time somehow exploitable by the wrong</div><div>party.</div><div><br></div><div>The two masks are located in sysfs at /sys/bus/ap/apmask and</div><div>/sys/bus/ap/aqmask.  The mask syntax is exactly the same as the</div><div>already existing mask attributes in the /sys/bus/ap directory (for</div><div>example ap_usage_domain_mask and ap_control_domain_mask).</div><div><br></div><div>By default all APQNs belong to the ap bus and the default drivers:</div><div><br></div><div>  cat /sys/bus/ap/apmask</div><div>  0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff</div><div>  cat /sys/bus/ap/aqmask</div><div>  0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff</div><div><br></div><div>The masks can be changed at boot time with the kernel command line</div><div>like this:</div><div><br></div><div>  ... ap.apmask=0xffff ap.aqmask=0x40</div><div><br></div><div>This would give these two pools:</div><div><br></div><div>  default drivers pool:    adapter 0 - 15, domain 1</div><div>  alternate drivers pool:  adapter 0 - 15, all but domain 1</div><div><span style="white-space:pre">                       </span>   adapter 16-255, all domains</div><div><br></div><div>The sysfs attributes for this two masks are writeable and an</div><div>administrator is able to reconfigure the assignements on the fly by</div><div>writing new mask values into.  With changing the mask(s) a revision of</div><div>the existing queue to driver bindings is done. So all APQNs which are</div><div>bound to the 'wrong' driver are reprobed via kernel function</div><div>device_reprobe() and thus the new correct driver will be assigned with</div><div>respect of the changed apmask and aqmask bits.</div><div><br></div><div>The mask values are bitmaps in big endian order starting with bit 0.</div><div>So adapter number 0 is the leftmost bit, mask is 0x8000... The sysfs</div><div>attributes accept 2 different formats:</div><div>- Absolute hex string starting with 0x like "0x12345678" does set</div><div>  the mask starting from left to right. If the given string is shorter</div><div>  than the mask it is padded with 0s on the right. If the string is</div><div>  longer than the mask an error comes back (EINVAL).</div><div>- '+' or '-' followed by a numerical value. Valid examples are "+1",</div><div>  "-13", "+0x41", "-0xff" and even "+0" and "-0". Only the addressed</div><div>  bit in the mask is switched on ('+') or off ('-').</div><div><br></div><div>This patch will also be the base for an upcoming extension to the</div><div>zcrypt drivers to be able to provide additional zcrypt device nodes</div><div>with filtering based on ap and aq masks.</div><div><br></div><div>Signed-off-by: Harald Freudenberger <<a href="mailto:freude@linux.ibm.com">freude@linux.ibm.com</a>></div><div>Signed-off-by: Martin Schwidefsky <<a href="mailto:schwidefsky@de.ibm.com">schwidefsky@de.ibm.com</a>></div><div>(cherry-picked from commit 7e0bdbe5c21cb8316a694e46ad5aad339f6894a6)</div><div>Signed-off-by: Frank Heimes <<a href="mailto:frank.heimes@canonical.com">frank.heimes@canonical.com</a>></div><div><br></div><div>---</div><div><br></div><div>diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c</div><div>index bf720ae..30d7898 100644</div><div>--- a/drivers/s390/crypto/ap_bus.c</div><div>+++ b/drivers/s390/crypto/ap_bus.c</div><div>@@ -34,6 +34,7 @@</div><div> #include <linux/crypto.h></div><div> #include <linux/mod_devicetable.h></div><div> #include <linux/debugfs.h></div><div>+#include <linux/ctype.h></div><div> </div><div> #include "ap_bus.h"</div><div> #include "ap_debug.h"</div><div>@@ -51,11 +52,26 @@ static int ap_thread_flag;</div><div> module_param_named(poll_thread, ap_thread_flag, int, 0440);</div><div> MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");</div><div> </div><div>+static char *apm_str;</div><div>+module_param_named(apmask, apm_str, charp, 0440);</div><div>+MODULE_PARM_DESC(apmask, "AP bus adapter mask.");</div><div>+</div><div>+static char *aqm_str;</div><div>+module_param_named(aqmask, aqm_str, charp, 0440);</div><div>+MODULE_PARM_DESC(aqmask, "AP bus domain mask.");</div><div>+</div><div> static struct device *ap_root_device;</div><div> </div><div> DEFINE_SPINLOCK(ap_list_lock);</div><div> LIST_HEAD(ap_card_list);</div><div> </div><div>+/* Default permissions (card and domain masking) */</div><div>+static struct ap_perms {</div><div>+       DECLARE_BITMAP(apm, AP_DEVICES);</div><div>+       DECLARE_BITMAP(aqm, AP_DOMAINS);</div><div>+} ap_perms;</div><div>+static DEFINE_MUTEX(ap_perms_mutex);</div><div>+</div><div> static struct ap_config_info *ap_configuration;</div><div> static bool initialised;</div><div> </div><div>@@ -670,11 +686,97 @@ static struct bus_type ap_bus_type = {</div><div>        .pm = &ap_bus_pm_ops,</div><div> };</div><div> </div><div>+static int __ap_revise_reserved(struct device *dev, void *dummy)</div><div>+{</div><div>+       int rc, card, queue, devres, drvres;</div><div>+</div><div>+       if (is_queue_dev(dev)) {</div><div>+               card = AP_QID_CARD(to_ap_queue(dev)->qid);</div><div>+               queue = AP_QID_QUEUE(to_ap_queue(dev)->qid);</div><div>+               mutex_lock(&ap_perms_mutex);</div><div>+               devres = test_bit_inv(card, ap_perms.apm)</div><div>+                       && test_bit_inv(queue, ap_perms.aqm);</div><div>+               mutex_unlock(&ap_perms_mutex);</div><div>+               drvres = to_ap_drv(dev->driver)->flags</div><div>+                       & AP_DRIVER_FLAG_DEFAULT;</div><div>+               if (!!devres != !!drvres) {</div><div>+                       AP_DBF(DBF_DEBUG, "reprobing queue=%02x.%04x\n",</div><div>+                              card, queue);</div><div>+                       rc = device_reprobe(dev);</div><div>+               }</div><div>+       }</div><div>+</div><div>+       return 0;</div><div>+}</div><div>+</div><div>+static void ap_bus_revise_bindings(void)</div><div>+{</div><div>+       bus_for_each_dev(&ap_bus_type, NULL, NULL, __ap_revise_reserved);</div><div>+}</div><div>+</div><div>+int ap_owned_by_def_drv(int card, int queue)</div><div>+{</div><div>+       int rc = 0;</div><div>+</div><div>+       if (card < 0 || card >= AP_DEVICES || queue < 0 || queue >= AP_DOMAINS)</div><div>+               return -EINVAL;</div><div>+</div><div>+       mutex_lock(&ap_perms_mutex);</div><div>+</div><div>+       if (test_bit_inv(card, ap_perms.apm)</div><div>+           && test_bit_inv(queue, ap_perms.aqm))</div><div>+               rc = 1;</div><div>+</div><div>+       mutex_unlock(&ap_perms_mutex);</div><div>+</div><div>+       return rc;</div><div>+}</div><div>+EXPORT_SYMBOL(ap_owned_by_def_drv);</div><div>+</div><div>+int ap_apqn_in_matrix_owned_by_def_drv(unsigned long *apm,</div><div>+                                      unsigned long *aqm)</div><div>+{</div><div>+       int card, queue, rc = 0;</div><div>+</div><div>+       mutex_lock(&ap_perms_mutex);</div><div>+</div><div>+       for (card = 0; !rc && card < AP_DEVICES; card++)</div><div>+               if (test_bit_inv(card, apm) &&</div><div>+                   test_bit_inv(card, ap_perms.apm))</div><div>+                       for (queue = 0; !rc && queue < AP_DOMAINS; queue++)</div><div>+                               if (test_bit_inv(queue, aqm) &&</div><div>+                                   test_bit_inv(queue, ap_perms.aqm))</div><div>+                                       rc = 1;</div><div>+</div><div>+       mutex_unlock(&ap_perms_mutex);</div><div>+</div><div>+       return rc;</div><div>+}</div><div>+EXPORT_SYMBOL(ap_apqn_in_matrix_owned_by_def_drv);</div><div>+</div><div> static int ap_device_probe(struct device *dev)</div><div> {</div><div>        struct ap_device *ap_dev = to_ap_dev(dev);</div><div>        struct ap_driver *ap_drv = to_ap_drv(dev->driver);</div><div>-       int rc;</div><div>+       int card, queue, devres, drvres, rc;</div><div>+</div><div>+       if (is_queue_dev(dev)) {</div><div>+               /*</div><div>+                * If the apqn is marked as reserved/used by ap bus and</div><div>+                * default drivers, only probe with drivers with the default</div><div>+                * flag set. If it is not marked, only probe with drivers</div><div>+                * with the default flag not set.</div><div>+                */</div><div>+               card = AP_QID_CARD(to_ap_queue(dev)->qid);</div><div>+               queue = AP_QID_QUEUE(to_ap_queue(dev)->qid);</div><div>+               mutex_lock(&ap_perms_mutex);</div><div>+               devres = test_bit_inv(card, ap_perms.apm)</div><div>+                       && test_bit_inv(queue, ap_perms.aqm);</div><div>+               mutex_unlock(&ap_perms_mutex);</div><div>+               drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;</div><div>+               if (!!devres != !!drvres)</div><div>+                       return -ENODEV;</div><div>+       }</div><div> </div><div>        /* Add queue/card to list of active queues/cards */</div><div>        spin_lock_bh(&ap_list_lock);</div><div>@@ -757,6 +859,36 @@ EXPORT_SYMBOL(ap_bus_force_rescan);</div><div> /*</div><div>  * AP bus attributes.</div><div>  */</div><div>+</div><div>+static int hex2bitmap(const char *str, unsigned long *bitmap, int bits)</div><div>+{</div><div>+       int i, n, b;</div><div>+</div><div>+       /* bits needs to be a multiple of 8 */</div><div>+       if (bits & 0x07)</div><div>+               return -EINVAL;</div><div>+</div><div>+       memset(bitmap, 0, bits / 8);</div><div>+</div><div>+       if (str[0] == '0' && str[1] == 'x')</div><div>+               str++;</div><div>+       if (*str == 'x')</div><div>+               str++;</div><div>+</div><div>+       for (i = 0; isxdigit(*str) && i < bits; str++) {</div><div>+               b = hex_to_bin(*str);</div><div>+               for (n = 0; n < 4; n++)</div><div>+                       if (b & (0x08 >> n))</div><div>+                               set_bit_inv(i + n, bitmap);</div><div>+               i += 4;</div><div>+       }</div><div>+</div><div>+       if (i < 4 || isxdigit(*str))</div><div>+               return -EINVAL;</div><div>+</div><div>+       return 0;</div><div>+}</div><div>+</div><div> static ssize_t ap_domain_show(struct bus_type *bus, char *buf)</div><div> {</div><div>        return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);</div><div>@@ -768,7 +900,8 @@ static ssize_t ap_domain_store(struct bus_type *bus,</div><div>        int domain;</div><div> </div><div>        if (sscanf(buf, "%i\n", &domain) != 1 ||</div><div>-           domain < 0 || domain > ap_max_domain_id)</div><div>+           domain < 0 || domain > ap_max_domain_id ||</div><div>+           !test_bit_inv(domain, ap_perms.aqm))</div><div>                return -EINVAL;</div><div>        spin_lock_bh(&ap_domain_lock);</div><div>        ap_domain_index = domain;</div><div>@@ -903,6 +1036,114 @@ static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf)</div><div> </div><div> static BUS_ATTR_RO(ap_max_domain_id);</div><div> </div><div>+static ssize_t apmask_show(struct bus_type *bus, char *buf)</div><div>+{</div><div>+       int rc;</div><div>+</div><div>+       if (mutex_lock_interruptible(&ap_perms_mutex))</div><div>+               return -ERESTARTSYS;</div><div>+       rc = snprintf(buf, PAGE_SIZE,</div><div>+                     "0x%016lx%016lx%016lx%016lx\n",</div><div>+                     ap_perms.apm[0], ap_perms.apm[1],</div><div>+                     ap_perms.apm[2], ap_perms.apm[3]);</div><div>+       mutex_unlock(&ap_perms_mutex);</div><div>+</div><div>+       return rc;</div><div>+}</div><div>+</div><div>+static ssize_t apmask_store(struct bus_type *bus, const char *buf,</div><div>+                           size_t count)</div><div>+{</div><div>+       int i;</div><div>+</div><div>+       if (*buf == '+' || *buf == '-') {</div><div>+               if (kstrtoint(buf, 0, &i))</div><div>+                       return -EINVAL;</div><div>+               if (i <= -AP_DEVICES || i >= AP_DEVICES)</div><div>+                       return -EINVAL;</div><div>+               if (mutex_lock_interruptible(&ap_perms_mutex))</div><div>+                       return -ERESTARTSYS;</div><div>+               if (*buf == '-')</div><div>+                       clear_bit_inv(-i, ap_perms.apm);</div><div>+               else</div><div>+                       set_bit_inv(i, ap_perms.apm);</div><div>+       } else {</div><div>+               DECLARE_BITMAP(apm, AP_DEVICES);</div><div>+</div><div>+               i = hex2bitmap(buf, apm, AP_DEVICES);</div><div>+               if (i)</div><div>+                       return i;</div><div>+               if (mutex_lock_interruptible(&ap_perms_mutex))</div><div>+                       return -ERESTARTSYS;</div><div>+               for (i = 0; i < AP_DEVICES; i++)</div><div>+                       if (test_bit_inv(i, apm))</div><div>+                               set_bit_inv(i, ap_perms.apm);</div><div>+                       else</div><div>+                               clear_bit_inv(i, ap_perms.apm);</div><div>+       }</div><div>+       mutex_unlock(&ap_perms_mutex);</div><div>+</div><div>+       ap_bus_revise_bindings();</div><div>+</div><div>+       return count;</div><div>+}</div><div>+</div><div>+static BUS_ATTR_RW(apmask);</div><div>+</div><div>+static ssize_t aqmask_show(struct bus_type *bus, char *buf)</div><div>+{</div><div>+       int rc;</div><div>+</div><div>+       if (mutex_lock_interruptible(&ap_perms_mutex))</div><div>+               return -ERESTARTSYS;</div><div>+       rc = snprintf(buf, PAGE_SIZE,</div><div>+                     "0x%016lx%016lx%016lx%016lx\n",</div><div>+                     ap_perms.aqm[0], ap_perms.aqm[1],</div><div>+                     ap_perms.aqm[2], ap_perms.aqm[3]);</div><div>+       mutex_unlock(&ap_perms_mutex);</div><div>+</div><div>+       return rc;</div><div>+}</div><div>+</div><div>+static ssize_t aqmask_store(struct bus_type *bus, const char *buf,</div><div>+                           size_t count)</div><div>+{</div><div>+       int i;</div><div>+</div><div>+       if (*buf == '+' || *buf == '-') {</div><div>+               if (kstrtoint(buf, 0, &i))</div><div>+                       return -EINVAL;</div><div>+               if (i <= -AP_DEVICES || i >= AP_DEVICES)</div><div>+                       return -EINVAL;</div><div>+               if (mutex_lock_interruptible(&ap_perms_mutex))</div><div>+                       return -ERESTARTSYS;</div><div>+               if (*buf == '-')</div><div>+                       clear_bit_inv(-i, ap_perms.aqm);</div><div>+               else</div><div>+                       set_bit_inv(i, ap_perms.aqm);</div><div>+       } else {</div><div>+               DECLARE_BITMAP(aqm, AP_DEVICES);</div><div>+</div><div>+               i = hex2bitmap(buf, aqm, AP_DEVICES);</div><div>+               if (i)</div><div>+                       return i;</div><div>+               if (mutex_lock_interruptible(&ap_perms_mutex))</div><div>+                       return -ERESTARTSYS;</div><div>+               for (i = 0; i < AP_DEVICES; i++)</div><div>+                       if (test_bit_inv(i, aqm))</div><div>+                               set_bit_inv(i, ap_perms.aqm);</div><div>+                       else</div><div>+                               clear_bit_inv(i, ap_perms.aqm);</div><div>+       }</div><div>+       mutex_unlock(&ap_perms_mutex);</div><div>+</div><div>+       ap_bus_revise_bindings();</div><div>+</div><div>+       return count;</div><div>+}</div><div>+</div><div>+static BUS_ATTR_RW(aqmask);</div><div>+</div><div> static struct bus_attribute *const ap_bus_attrs[] = {</div><div>        &bus_attr_ap_domain,</div><div>        &bus_attr_ap_control_domain_mask,</div><div>@@ -912,6 +1153,8 @@ static struct bus_attribute *const ap_bus_attrs[] = {</div><div>        &bus_attr_ap_interrupts,</div><div>        &bus_attr_poll_timeout,</div><div>        &bus_attr_ap_max_domain_id,</div><div>+       &bus_attr_apmask,</div><div>+       &bus_attr_aqmask,</div><div>        NULL,</div><div> };</div><div> </div><div>@@ -940,7 +1183,8 @@ static int ap_select_domain(void)</div><div>        best_domain = -1;</div><div>        max_count = 0;</div><div>        for (i = 0; i < AP_DOMAINS; i++) {</div><div>-               if (!ap_test_config_domain(i))</div><div>+               if (!ap_test_config_domain(i) ||</div><div>+                   !test_bit_inv(i, ap_perms.aqm))</div><div>                        continue;</div><div>                count = 0;</div><div>                for (j = 0; j < AP_DEVICES; j++) {</div><div>@@ -1190,6 +1434,37 @@ static int __init ap_debug_init(void)</div><div>        return 0;</div><div> }</div><div> </div><div>+static void __init ap_perms_init(void)</div><div>+{</div><div>+       int i, rc;</div><div>+</div><div>+       /* start with all resources useable */</div><div>+       memset(&ap_perms.apm, 0xFF, sizeof(ap_perms.apm));</div><div>+       memset(&ap_perms.aqm, 0xFF, sizeof(ap_perms.aqm));</div><div>+</div><div>+       /* process kernel parameters apm and aqm if given */</div><div>+       if (apm_str) {</div><div>+               DECLARE_BITMAP(apm, AP_DEVICES);</div><div>+</div><div>+               rc = hex2bitmap(apm_str, apm, AP_DEVICES);</div><div>+               if (rc == 0) {</div><div>+                       for (i = 0; i < AP_DEVICES; i++)</div><div>+                               if (!test_bit_inv(i, apm))</div><div>+                                       clear_bit_inv(i, ap_perms.apm);</div><div>+               }</div><div>+       }</div><div>+       if (aqm_str) {</div><div>+               DECLARE_BITMAP(aqm, AP_DOMAINS);</div><div>+</div><div>+               rc = hex2bitmap(aqm_str, aqm, AP_DOMAINS);</div><div>+               if (rc == 0) {</div><div>+                       for (i = 0; i < AP_DOMAINS; i++)</div><div>+                               if (!test_bit_inv(i, aqm))</div><div>+                                       clear_bit_inv(i, ap_perms.aqm);</div><div>+               }</div><div>+       }</div><div>+}</div><div>+</div><div> /**</div><div>  * ap_module_init(): The module initialization code.</div><div>  *</div><div>@@ -1209,6 +1484,9 @@ static int __init ap_module_init(void)</div><div>                return -ENODEV;</div><div>        }</div><div> </div><div>+       /* set up the AP permissions (ap and aq masks) */</div><div>+       ap_perms_init();</div><div>+</div><div>        /* Get AP configuration data if available */</div><div>        ap_init_configuration();</div><div> </div><div>@@ -1217,7 +1495,9 @@ static int __init ap_module_init(void)</div><div>                        ap_max_domain_id ? ap_max_domain_id : AP_DOMAINS - 1;</div><div>        else</div><div>                max_domain_id = 15;</div><div>-       if (ap_domain_index < -1 || ap_domain_index > max_domain_id) {</div><div>+       if (ap_domain_index < -1 || ap_domain_index > max_domain_id ||</div><div>+           (ap_domain_index >= 0 &&</div><div>+            !test_bit_inv(ap_domain_index, ap_perms.aqm))) {</div><div>                pr_warn("%d is not a valid cryptographic domain\n",</div><div>                        ap_domain_index);</div><div>                ap_domain_index = -1;</div><div>diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h</div><div>index 24d3425..5246cd8 100644</div><div>--- a/drivers/s390/crypto/ap_bus.h</div><div>+++ b/drivers/s390/crypto/ap_bus.h</div><div>@@ -117,9 +117,18 @@ enum ap_wait {</div><div> struct ap_device;</div><div> struct ap_message;</div><div> </div><div>+/*</div><div>+ * The ap driver struct includes a flags field which holds some info for</div><div>+ * the ap bus about the driver. Currently only one flag is supported and</div><div>+ * used: The DEFAULT flag marks an ap driver as a default driver which is</div><div>+ * used together with the apmask and aqmask whitelisting of the ap bus.</div><div>+ */</div><div>+#define AP_DRIVER_FLAG_DEFAULT 0x0001</div><div>+</div><div> struct ap_driver {</div><div>        struct device_driver driver;</div><div>        struct ap_device_id *ids;</div><div>+       unsigned int flags;</div><div> </div><div>        int (*probe)(struct ap_device *);</div><div>        void (*remove)(struct ap_device *);</div><div>@@ -248,4 +257,27 @@ void ap_queue_resume(struct ap_device *ap_dev);</div><div> struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type,</div><div>                               int comp_device_type, unsigned int functions);</div><div> </div><div>+/*</div><div>+ * check APQN for owned/reserved by ap bus and default driver(s).</div><div>+ * Checks if this APQN is or will be in use by the ap bus</div><div>+ * and the default set of drivers.</div><div>+ * If yes, returns 1, if not returns 0. On error a negative</div><div>+ * errno value is returned.</div><div>+ */</div><div>+int ap_owned_by_def_drv(int card, int queue);</div><div>+</div><div>+/*</div><div>+ * check 'matrix' of APQNs for owned/reserved by ap bus and</div><div>+ * default driver(s).</div><div>+ * Checks if there is at least one APQN in the given 'matrix'</div><div>+ * marked as owned/reserved by the ap bus and default driver(s).</div><div>+ * If such an APQN is found the return value is 1, otherwise</div><div>+ * 0 is returned. On error a negative errno value is returned.</div><div>+ * The parameter apm is a bitmask which should be declared</div><div>+ * as DECLARE_BITMAP(apm, AP_DEVICES), the aqm parameter is</div><div>+ * similar, should be declared as DECLARE_BITMAP(aqm, AP_DOMAINS).</div><div>+ */</div><div>+int ap_apqn_in_matrix_owned_by_def_drv(unsigned long *apm,</div><div>+                                      unsigned long *aqm);</div><div>+</div><div> #endif /* _AP_BUS_H_ */</div><div>diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c</div><div>index e701194..f4ae5fa 100644</div><div>--- a/drivers/s390/crypto/zcrypt_cex2a.c</div><div>+++ b/drivers/s390/crypto/zcrypt_cex2a.c</div><div>@@ -145,6 +145,7 @@ static struct ap_driver zcrypt_cex2a_card_driver = {</div><div>        .probe = zcrypt_cex2a_card_probe,</div><div>        .remove = zcrypt_cex2a_card_remove,</div><div>        .ids = zcrypt_cex2a_card_ids,</div><div>+       .flags = AP_DRIVER_FLAG_DEFAULT,</div><div> };</div><div> </div><div> /**</div><div>@@ -208,6 +209,7 @@ static struct ap_driver zcrypt_cex2a_queue_driver = {</div><div>        .suspend = ap_queue_suspend,</div><div>        .resume = ap_queue_resume,</div><div>        .ids = zcrypt_cex2a_queue_ids,</div><div>+       .flags = AP_DRIVER_FLAG_DEFAULT,</div><div> };</div><div> </div><div> int __init zcrypt_cex2a_init(void)</div><div>diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c</div><div>index f305538..35d58db 100644</div><div>--- a/drivers/s390/crypto/zcrypt_cex4.c</div><div>+++ b/drivers/s390/crypto/zcrypt_cex4.c</div><div>@@ -214,6 +214,7 @@ static struct ap_driver zcrypt_cex4_card_driver = {</div><div>        .probe = zcrypt_cex4_card_probe,</div><div>        .remove = zcrypt_cex4_card_remove,</div><div>        .ids = zcrypt_cex4_card_ids,</div><div>+       .flags = AP_DRIVER_FLAG_DEFAULT,</div><div> };</div><div> </div><div> /**</div><div>@@ -283,6 +284,7 @@ static struct ap_driver zcrypt_cex4_queue_driver = {</div><div>        .suspend = ap_queue_suspend,</div><div>        .resume = ap_queue_resume,</div><div>        .ids = zcrypt_cex4_queue_ids,</div><div>+       .flags = AP_DRIVER_FLAG_DEFAULT,</div><div> };</div><div> </div><div> int __init zcrypt_cex4_init(void)</div><div>diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c</div><div>index 0d639dd..94d9f72 100644</div><div>--- a/drivers/s390/crypto/zcrypt_pcixcc.c</div><div>+++ b/drivers/s390/crypto/zcrypt_pcixcc.c</div><div>@@ -223,6 +223,7 @@ static struct ap_driver zcrypt_pcixcc_card_driver = {</div><div>        .probe = zcrypt_pcixcc_card_probe,</div><div>        .remove = zcrypt_pcixcc_card_remove,</div><div>        .ids = zcrypt_pcixcc_card_ids,</div><div>+       .flags = AP_DRIVER_FLAG_DEFAULT,</div><div> };</div><div> </div><div> /**</div><div>@@ -286,6 +287,7 @@ static struct ap_driver zcrypt_pcixcc_queue_driver = {</div><div>        .suspend = ap_queue_suspend,</div><div>        .resume = ap_queue_resume,</div><div>        .ids = zcrypt_pcixcc_queue_ids,</div><div>+       .flags = AP_DRIVER_FLAG_DEFAULT,</div><div> };</div><div> </div><div> int __init zcrypt_pcixcc_init(void)</div><div><br></div></div></div>