*/
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)