list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
                list_del_init(&ap_msg->list);
                ap_dev->pendingq_count--;
-               ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+               ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
        }
        list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
                list_del_init(&ap_msg->list);
                ap_dev->requestq_count--;
-               ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+               ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
        }
 }
 
                                continue;
                        list_del_init(&ap_msg->list);
                        ap_dev->pendingq_count--;
-                       ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply);
+                       ap_msg->receive(ap_dev, ap_msg, ap_dev->reply);
                        break;
                }
                if (ap_dev->queue_count > 0)
                        return -EBUSY;
                case AP_RESPONSE_REQ_FAC_NOT_INST:
                case AP_RESPONSE_MESSAGE_TOO_BIG:
-                       ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
+                       ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
                        return -EINVAL;
                default:        /* Device is gone. */
-                       ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+                       ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
                        return -ENODEV;
                }
        } else {
        unsigned long flags;
        int rc;
 
+       /* For asynchronous message handling a valid receive-callback
+        * is required. */
+       BUG_ON(!ap_msg->receive);
+
        spin_lock_bh(&ap_dev->lock);
        if (!ap_dev->unregistered) {
                /* Make room on the queue by polling for finished requests. */
                if (rc == -ENODEV)
                        ap_dev->unregistered = 1;
        } else {
-               ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+               ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
                rc = -ENODEV;
        }
        spin_unlock_bh(&ap_dev->lock);
 
 
        int (*probe)(struct ap_device *);
        void (*remove)(struct ap_device *);
-       /* receive is called from tasklet context */
-       void (*receive)(struct ap_device *, struct ap_message *,
-                       struct ap_message *);
        int request_timeout;            /* request timeout in jiffies */
 };
 
 
        void *private;                  /* ap driver private pointer. */
        unsigned int special:1;         /* Used for special commands. */
+       /* receive is called from tasklet context */
+       void (*receive)(struct ap_device *, struct ap_message *,
+                       struct ap_message *);
 };
 
 #define AP_DEVICE(dt)                                  \
        ap_msg->psmid = 0;
        ap_msg->length = 0;
        ap_msg->special = 0;
+       ap_msg->receive = NULL;
 }
 
 /*
 
 static struct ap_driver zcrypt_cex2a_driver = {
        .probe = zcrypt_cex2a_probe,
        .remove = zcrypt_cex2a_remove,
-       .receive = zcrypt_cex2a_receive,
        .ids = zcrypt_cex2a_ids,
        .request_timeout = CEX2A_CLEANUP_TIME,
 };
                ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL);
        if (!ap_msg.message)
                return -ENOMEM;
+       ap_msg.receive = zcrypt_cex2a_receive;
        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
        ap_msg.private = &work;
                ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL);
        if (!ap_msg.message)
                return -ENOMEM;
+       ap_msg.receive = zcrypt_cex2a_receive;
        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
        ap_msg.private = &work;
 
 static struct ap_driver zcrypt_pcica_driver = {
        .probe = zcrypt_pcica_probe,
        .remove = zcrypt_pcica_remove,
-       .receive = zcrypt_pcica_receive,
        .ids = zcrypt_pcica_ids,
        .request_timeout = PCICA_CLEANUP_TIME,
 };
        ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
        if (!ap_msg.message)
                return -ENOMEM;
+       ap_msg.receive = zcrypt_pcica_receive;
        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
        ap_msg.private = &work;
        ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
        if (!ap_msg.message)
                return -ENOMEM;
+       ap_msg.receive = zcrypt_pcica_receive;
        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
        ap_msg.private = &work;
 
 static struct ap_driver zcrypt_pcicc_driver = {
        .probe = zcrypt_pcicc_probe,
        .remove = zcrypt_pcicc_remove,
-       .receive = zcrypt_pcicc_receive,
        .ids = zcrypt_pcicc_ids,
        .request_timeout = PCICC_CLEANUP_TIME,
 };
        ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
        if (!ap_msg.message)
                return -ENOMEM;
+       ap_msg.receive = zcrypt_pcicc_receive;
        ap_msg.length = PAGE_SIZE;
        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
        ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
        if (!ap_msg.message)
                return -ENOMEM;
+       ap_msg.receive = zcrypt_pcicc_receive;
        ap_msg.length = PAGE_SIZE;
        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
 
 static struct ap_driver zcrypt_pcixcc_driver = {
        .probe = zcrypt_pcixcc_probe,
        .remove = zcrypt_pcixcc_remove,
-       .receive = zcrypt_pcixcc_receive,
        .ids = zcrypt_pcixcc_ids,
        .request_timeout = PCIXCC_CLEANUP_TIME,
 };
        ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
        if (!ap_msg.message)
                return -ENOMEM;
+       ap_msg.receive = zcrypt_pcixcc_receive;
        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
        ap_msg.private = &resp_type;
        ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
        if (!ap_msg.message)
                return -ENOMEM;
+       ap_msg.receive = zcrypt_pcixcc_receive;
        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
        ap_msg.private = &resp_type;
        ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
        if (!ap_msg.message)
                return -ENOMEM;
+       ap_msg.receive = zcrypt_pcixcc_receive;
        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
        ap_msg.private = &resp_type;
        ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
        if (!ap_msg.message)
                return -ENOMEM;
+       ap_msg.receive = zcrypt_pcixcc_receive;
        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
                                atomic_inc_return(&zcrypt_step);
        ap_msg.private = &resp_type;