#include <linux/mod_devicetable.h>
 #include <linux/debugfs.h>
 #include <linux/ctype.h>
+#include <linux/module.h>
 
 #include "ap_bus.h"
 #include "ap_debug.h"
        return 0;
 }
 
+static int ap_parse_bitmap_str(const char *str, unsigned long *bitmap, int bits,
+                              unsigned long *newmap)
+{
+       unsigned long size;
+       int rc;
+
+       size = BITS_TO_LONGS(bits) * sizeof(unsigned long);
+       if (*str == '+' || *str == '-') {
+               memcpy(newmap, bitmap, size);
+               rc = modify_bitmap(str, newmap, bits);
+       } else {
+               memset(newmap, 0, size);
+               rc = hex2bitmap(str, newmap, bits);
+       }
+       return rc;
+}
+
 int ap_parse_mask_str(const char *str,
                      unsigned long *bitmap, int bits,
                      struct mutex *lock)
                kfree(newmap);
                return -ERESTARTSYS;
        }
-
-       if (*str == '+' || *str == '-') {
-               memcpy(newmap, bitmap, size);
-               rc = modify_bitmap(str, newmap, bits);
-       } else {
-               memset(newmap, 0, size);
-               rc = hex2bitmap(str, newmap, bits);
-       }
+       rc = ap_parse_bitmap_str(str, bitmap, bits, newmap);
        if (rc == 0)
                memcpy(bitmap, newmap, size);
        mutex_unlock(lock);
        return rc;
 }
 
+static int __verify_card_reservations(struct device_driver *drv, void *data)
+{
+       int rc = 0;
+       struct ap_driver *ap_drv = to_ap_drv(drv);
+       unsigned long *newapm = (unsigned long *)data;
+
+       /*
+        * increase the driver's module refcounter to be sure it is not
+        * going away when we invoke the callback function.
+        */
+       if (!try_module_get(drv->owner))
+               return 0;
+
+       if (ap_drv->in_use) {
+               rc = ap_drv->in_use(newapm, ap_perms.aqm);
+               if (rc)
+                       rc = -EBUSY;
+       }
+
+       /* release the driver's module */
+       module_put(drv->owner);
+
+       return rc;
+}
+
+static int apmask_commit(unsigned long *newapm)
+{
+       int rc;
+       unsigned long reserved[BITS_TO_LONGS(AP_DEVICES)];
+
+       /*
+        * Check if any bits in the apmask have been set which will
+        * result in queues being removed from non-default drivers
+        */
+       if (bitmap_andnot(reserved, newapm, ap_perms.apm, AP_DEVICES)) {
+               rc = bus_for_each_drv(&ap_bus_type, NULL, reserved,
+                                     __verify_card_reservations);
+               if (rc)
+                       return rc;
+       }
+
+       memcpy(ap_perms.apm, newapm, APMASKSIZE);
+
+       return 0;
+}
+
 static ssize_t apmask_store(struct bus_type *bus, const char *buf,
                            size_t count)
 {
        int rc;
+       DECLARE_BITMAP(newapm, AP_DEVICES);
+
+       if (mutex_lock_interruptible(&ap_perms_mutex))
+               return -ERESTARTSYS;
 
-       rc = ap_parse_mask_str(buf, ap_perms.apm, AP_DEVICES, &ap_perms_mutex);
+       rc = ap_parse_bitmap_str(buf, ap_perms.apm, AP_DEVICES, newapm);
+       if (rc)
+               goto done;
+
+       rc = apmask_commit(newapm);
+
+done:
+       mutex_unlock(&ap_perms_mutex);
        if (rc)
                return rc;
 
        return rc;
 }
 
+static int __verify_queue_reservations(struct device_driver *drv, void *data)
+{
+       int rc = 0;
+       struct ap_driver *ap_drv = to_ap_drv(drv);
+       unsigned long *newaqm = (unsigned long *)data;
+
+       /*
+        * increase the driver's module refcounter to be sure it is not
+        * going away when we invoke the callback function.
+        */
+       if (!try_module_get(drv->owner))
+               return 0;
+
+       if (ap_drv->in_use) {
+               rc = ap_drv->in_use(ap_perms.apm, newaqm);
+               if (rc)
+                       return -EBUSY;
+       }
+
+       /* release the driver's module */
+       module_put(drv->owner);
+
+       return rc;
+}
+
+static int aqmask_commit(unsigned long *newaqm)
+{
+       int rc;
+       unsigned long reserved[BITS_TO_LONGS(AP_DOMAINS)];
+
+       /*
+        * Check if any bits in the aqmask have been set which will
+        * result in queues being removed from non-default drivers
+        */
+       if (bitmap_andnot(reserved, newaqm, ap_perms.aqm, AP_DOMAINS)) {
+               rc = bus_for_each_drv(&ap_bus_type, NULL, reserved,
+                                     __verify_queue_reservations);
+               if (rc)
+                       return rc;
+       }
+
+       memcpy(ap_perms.aqm, newaqm, AQMASKSIZE);
+
+       return 0;
+}
+
 static ssize_t aqmask_store(struct bus_type *bus, const char *buf,
                            size_t count)
 {
        int rc;
+       DECLARE_BITMAP(newaqm, AP_DOMAINS);
 
-       rc = ap_parse_mask_str(buf, ap_perms.aqm, AP_DOMAINS, &ap_perms_mutex);
+       if (mutex_lock_interruptible(&ap_perms_mutex))
+               return -ERESTARTSYS;
+
+       rc = ap_parse_bitmap_str(buf, ap_perms.aqm, AP_DOMAINS, newaqm);
+       if (rc)
+               goto done;
+
+       rc = aqmask_commit(newaqm);
+
+done:
+       mutex_unlock(&ap_perms_mutex);
        if (rc)
                return rc;