*/
 static int ap_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
-       int rc;
+       int rc = 0;
        struct ap_device *ap_dev = to_ap_dev(dev);
 
        /* Uevents from ap bus core don't need extensions to the env */
        if (dev == ap_root_device)
                return 0;
 
-       /* Set up DEV_TYPE environment variable. */
-       rc = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
-       if (rc)
-               return rc;
+       if (is_card_dev(dev)) {
+               struct ap_card *ac = to_ap_card(&ap_dev->device);
 
-       /* Add MODALIAS= */
-       rc = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
-       if (rc)
-               return rc;
+               /* Set up DEV_TYPE environment variable. */
+               rc = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
+               if (rc)
+                       return rc;
+               /* Add MODALIAS= */
+               rc = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
+               if (rc)
+                       return rc;
+
+               /* Add MODE=<accel|cca|ep11> */
+               if (ap_test_bit(&ac->functions, AP_FUNC_ACCEL))
+                       rc = add_uevent_var(env, "MODE=accel");
+               else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO))
+                       rc = add_uevent_var(env, "MODE=cca");
+               else if (ap_test_bit(&ac->functions, AP_FUNC_EP11))
+                       rc = add_uevent_var(env, "MODE=ep11");
+               if (rc)
+                       return rc;
+       } else {
+               struct ap_queue *aq = to_ap_queue(&ap_dev->device);
+
+               /* Add MODE=<accel|cca|ep11> */
+               if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL))
+                       rc = add_uevent_var(env, "MODE=accel");
+               else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO))
+                       rc = add_uevent_var(env, "MODE=cca");
+               else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11))
+                       rc = add_uevent_var(env, "MODE=ep11");
+               if (rc)
+                       return rc;
+       }
 
        return 0;
 }
        kobject_uevent_env(&ap_root_device->kobj, KOBJ_CHANGE, envp);
 }
 
+void ap_send_config_uevent(struct ap_device *ap_dev, bool cfg)
+{
+       char buf[16];
+       char *envp[] = { buf, NULL };
+
+       snprintf(buf, sizeof(buf), "CONFIG=%d", cfg ? 1 : 0);
+
+       kobject_uevent_env(&ap_dev->device.kobj, KOBJ_CHANGE, envp);
+}
+EXPORT_SYMBOL(ap_send_config_uevent);
+
+void ap_send_online_uevent(struct ap_device *ap_dev, int online)
+{
+       char buf[16];
+       char *envp[] = { buf, NULL };
+
+       snprintf(buf, sizeof(buf), "ONLINE=%d", online ? 1 : 0);
+
+       kobject_uevent_env(&ap_dev->device.kobj, KOBJ_CHANGE, envp);
+}
+EXPORT_SYMBOL(ap_send_online_uevent);
+
 /*
  * calc # of bound APQNs
  */
                        spin_unlock_bh(&aq->lock);
                        AP_DBF_INFO("%s(%d,%d) queue device config off\n",
                                    __func__, ac->id, dom);
+                       ap_send_config_uevent(&aq->ap_dev, aq->config);
                        /* 'receive' pending messages with -EAGAIN */
                        ap_flush_queue(aq);
                        goto put_dev_and_continue;
                        spin_unlock_bh(&aq->lock);
                        AP_DBF_INFO("%s(%d,%d) queue device config on\n",
                                    __func__, ac->id, dom);
+                       ap_send_config_uevent(&aq->ap_dev, aq->config);
                        goto put_dev_and_continue;
                }
                /* handle other error states */
                                ac->config = false;
                                AP_DBF_INFO("%s(%d) card device config off\n",
                                            __func__, ap);
-
+                               ap_send_config_uevent(&ac->ap_dev, ac->config);
                        }
                        if (!decfg && !ac->config) {
                                ac->config = true;
                                AP_DBF_INFO("%s(%d) card device config on\n",
                                            __func__, ap);
+                               ap_send_config_uevent(&ac->ap_dev, ac->config);
                        }
                }
        }
 
  */
 int ap_wait_init_apqn_bindings_complete(unsigned long timeout);
 
+void ap_send_config_uevent(struct ap_device *ap_dev, bool cfg);
+void ap_send_online_uevent(struct ap_device *ap_dev, int online);
+
 #endif /* _AP_BUS_H_ */
 
 
        ac->config = cfg ? true : false;
 
+       ap_send_config_uevent(&ac->ap_dev, ac->config);
+
        return count;
 }
 
 
 int zcrypt_queue_put(struct zcrypt_queue *);
 int zcrypt_queue_register(struct zcrypt_queue *);
 void zcrypt_queue_unregister(struct zcrypt_queue *);
-void zcrypt_queue_force_online(struct zcrypt_queue *, int);
+bool zcrypt_queue_force_online(struct zcrypt_queue *zq, int online);
 
 int zcrypt_rng_device_add(void);
 void zcrypt_rng_device_remove(void);
 
        struct ap_card *ac = to_ap_card(dev);
        struct zcrypt_card *zc = ac->private;
        struct zcrypt_queue *zq;
-       int online, id;
+       int online, id, i = 0, maxzqs = 0;
+       struct zcrypt_queue **zq_uelist = NULL;
 
        if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1)
                return -EINVAL;
 
        ZCRYPT_DBF(DBF_INFO, "card=%02x online=%d\n", id, online);
 
+       ap_send_online_uevent(&ac->ap_dev, online);
+
        spin_lock(&zcrypt_list_lock);
+       /*
+        * As we are in atomic context here, directly sending uevents
+        * does not work. So collect the zqueues in a dynamic array
+        * and process them after zcrypt_list_lock release. As we get/put
+        * the zqueue objects, we make sure they exist after lock release.
+        */
+       list_for_each_entry(zq, &zc->zqueues, list)
+               maxzqs++;
+       if (maxzqs > 0)
+               zq_uelist = kcalloc(maxzqs + 1, sizeof(zq), GFP_ATOMIC);
        list_for_each_entry(zq, &zc->zqueues, list)
-               zcrypt_queue_force_online(zq, online);
+               if (zcrypt_queue_force_online(zq, online))
+                       if (zq_uelist) {
+                               zcrypt_queue_get(zq);
+                               zq_uelist[i++] = zq;
+                       }
        spin_unlock(&zcrypt_list_lock);
+       if (zq_uelist) {
+               for (i = 0; zq_uelist[i]; i++) {
+                       zq = zq_uelist[i];
+                       ap_send_online_uevent(&zq->queue->ap_dev, online);
+                       zcrypt_queue_put(zq);
+               }
+               kfree(zq_uelist);
+       }
+
        return count;
 }
 
 
                               AP_QID_CARD(zq->queue->qid),
                               AP_QID_QUEUE(zq->queue->qid),
                               t80h->code);
+               ap_send_online_uevent(&zq->queue->ap_dev, zq->online);
                return -EAGAIN;
        }
        if (zq->zcard->user_space_type == ZCRYPT_CEX2A)
                               AP_QID_CARD(zq->queue->qid),
                               AP_QID_QUEUE(zq->queue->qid),
                               (int) rtype);
+               ap_send_online_uevent(&zq->queue->ap_dev, zq->online);
                return -EAGAIN;
        }
 }
 
                               AP_QID_CARD(zq->queue->qid),
                               AP_QID_QUEUE(zq->queue->qid),
                               (int) service_rc, (int) service_rs);
+               ap_send_online_uevent(&zq->queue->ap_dev, zq->online);
                return -EAGAIN;
        }
        data = msg->text;
                               AP_QID_CARD(zq->queue->qid),
                               AP_QID_QUEUE(zq->queue->qid),
                               (int) msg->hdr.type);
+               ap_send_online_uevent(&zq->queue->ap_dev, zq->online);
                return -EAGAIN;
        }
 }
                               AP_QID_CARD(zq->queue->qid),
                               AP_QID_QUEUE(zq->queue->qid),
                               (int) msg->hdr.type);
+               ap_send_online_uevent(&zq->queue->ap_dev, zq->online);
                return -EAGAIN;
        }
 }
                               AP_QID_CARD(zq->queue->qid),
                               AP_QID_QUEUE(zq->queue->qid),
                               (int) msg->hdr.type);
+               ap_send_online_uevent(&zq->queue->ap_dev, zq->online);
                return -EAGAIN;
        }
 }
                               AP_QID_CARD(zq->queue->qid),
                               AP_QID_QUEUE(zq->queue->qid),
                               (int) msg->hdr.type);
+               ap_send_online_uevent(&zq->queue->ap_dev, zq->online);
                return -EAGAIN;
        }
 }
 
                   AP_QID_QUEUE(zq->queue->qid),
                   online);
 
+       ap_send_online_uevent(&aq->ap_dev, online);
+
        if (!online)
                ap_flush_queue(zq->queue);
        return count;
        .attrs = zcrypt_queue_attrs,
 };
 
-void zcrypt_queue_force_online(struct zcrypt_queue *zq, int online)
+bool zcrypt_queue_force_online(struct zcrypt_queue *zq, int online)
 {
-       zq->online = online;
-       if (!online)
-               ap_flush_queue(zq->queue);
+       if (!!zq->online != !!online) {
+               zq->online = online;
+               if (!online)
+                       ap_flush_queue(zq->queue);
+               return true;
+       }
+       return false;
 }
 
 struct zcrypt_queue *zcrypt_queue_alloc(size_t max_response_size)