mirror of https://gitee.com/openkylin/linux.git
s390/ap/zcrypt: notify userspace with online, config and mode info
This patch brings 3 reworked/new uevent changes: * All AP uevents caused by an ap card or queue device now carry an additional uevent env value MODE=<accel|cca|ep11>. Here is an example: KERNEL[1267.301292] add /devices/ap/card0a (ap) ACTION=add DEVPATH=/devices/ap/card0a SUBSYSTEM=ap DEVTYPE=ap_card DEV_TYPE=000D MODALIAS=ap:t0D MODE=ep11 <- this is new SEQNUM=1095 This is true for bind, unbind, add, remove, and change uevents related to ap card or ap queue devices. * On a change of the soft online attribute on a zcrypt queue or card device a new CHANGE uevent is sent with an env value ONLINE=<0|1>. Example uevent: KERNEL[613.067531] change /devices/ap/card09/09.0011 (ap) ACTION=change DEVPATH=/devices/ap/card09/09.0011 SUBSYSTEM=ap ONLINE=0 <- this is new DEVTYPE=ap_queue DRIVER=cex4queue MODE=cca SEQNUM=1070 - On a change of the config state of an zcrypt card device a new CHANGE uevent is sent with an env value CONFIG=<0|1>. Example uevent: KERNEL[876.258680] change /devices/ap/card09 (ap) ACTION=change DEVPATH=/devices/ap/card09 SUBSYSTEM=ap CONFIG=0 <- this is new DEVTYPE=ap_card DRIVER=cex4card DEV_TYPE=000D MODALIAS=ap:t0D MODE=cca SEQNUM=1073 Setting a card config on/off causes the dependent queue devices to follow the config state change and thus uevents informing about the config state change for the queue devices are also emitted. Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
113af8e6f4
commit
df6f508c68
|
@ -587,22 +587,47 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv)
|
|||
*/
|
||||
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;
|
||||
}
|
||||
|
@ -624,6 +649,28 @@ static void ap_send_bindings_complete_uevent(void)
|
|||
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
|
||||
*/
|
||||
|
@ -1546,6 +1593,7 @@ static inline void ap_scan_domains(struct ap_card *ac)
|
|||
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;
|
||||
|
@ -1560,6 +1608,7 @@ static inline void ap_scan_domains(struct ap_card *ac)
|
|||
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 */
|
||||
|
@ -1669,12 +1718,13 @@ static inline void ap_scan_adapter(int ap)
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -362,4 +362,7 @@ int ap_parse_mask_str(const char *str,
|
|||
*/
|
||||
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_ */
|
||||
|
|
|
@ -167,6 +167,8 @@ static ssize_t config_store(struct device *dev,
|
|||
|
||||
ac->config = cfg ? true : false;
|
||||
|
||||
ap_send_config_uevent(&ac->ap_dev, ac->config);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ void zcrypt_queue_get(struct zcrypt_queue *);
|
|||
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);
|
||||
|
|
|
@ -64,7 +64,8 @@ static ssize_t online_store(struct device *dev,
|
|||
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;
|
||||
|
@ -77,10 +78,35 @@ static ssize_t online_store(struct device *dev,
|
|||
|
||||
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)
|
||||
zcrypt_queue_force_online(zq, online);
|
||||
maxzqs++;
|
||||
if (maxzqs > 0)
|
||||
zq_uelist = kcalloc(maxzqs + 1, sizeof(zq), GFP_ATOMIC);
|
||||
list_for_each_entry(zq, &zc->zqueues, list)
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -375,6 +375,7 @@ static int convert_type80(struct zcrypt_queue *zq,
|
|||
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)
|
||||
|
@ -412,6 +413,7 @@ static int convert_response_cex2a(struct zcrypt_queue *zq,
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -675,6 +675,7 @@ static int convert_type86_ica(struct zcrypt_queue *zq,
|
|||
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;
|
||||
|
@ -820,6 +821,7 @@ static int convert_response_ica(struct zcrypt_queue *zq,
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -854,6 +856,7 @@ static int convert_response_xcrb(bool userspace, struct zcrypt_queue *zq,
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -883,6 +886,7 @@ static int convert_response_ep11_xcrb(bool userspace, struct zcrypt_queue *zq,
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -913,6 +917,7 @@ static int convert_response_rng(struct zcrypt_queue *zq,
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,8 @@ static ssize_t online_store(struct device *dev,
|
|||
AP_QID_QUEUE(zq->queue->qid),
|
||||
online);
|
||||
|
||||
ap_send_online_uevent(&aq->ap_dev, online);
|
||||
|
||||
if (!online)
|
||||
ap_flush_queue(zq->queue);
|
||||
return count;
|
||||
|
@ -98,11 +100,15 @@ static const struct attribute_group zcrypt_queue_attr_group = {
|
|||
.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)
|
||||
|
|
Loading…
Reference in New Issue