^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Deliver z/VM CP special messages (SMSG) as uevents.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * The driver registers for z/VM CP special messages with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * "APP" prefix. Incoming messages are delivered to user space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * as uevents.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright IBM Corp. 2010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define KMSG_COMPONENT "smsgiucv_app"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <net/iucv/iucv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "smsgiucv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* prefix used for SMSG registration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SMSG_PREFIX "APP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* SMSG related uevent environment variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ENV_SENDER_STR "SMSG_SENDER="
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define ENV_SENDER_LEN (strlen(ENV_SENDER_STR) + 8 + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define ENV_PREFIX_STR "SMSG_ID="
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define ENV_PREFIX_LEN (strlen(ENV_PREFIX_STR) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) strlen(SMSG_PREFIX) + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define ENV_TEXT_STR "SMSG_TEXT="
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define ENV_TEXT_LEN(msg) (strlen(ENV_TEXT_STR) + strlen((msg)) + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* z/VM user ID which is permitted to send SMSGs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * If the value is undefined or empty (""), special messages are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * accepted from any z/VM user ID. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static char *sender;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) module_param(sender, charp, 0400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MODULE_PARM_DESC(sender, "z/VM user ID from which CP SMSGs are accepted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* SMSG device representation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static struct device *smsg_app_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* list element for queuing received messages for delivery */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct smsg_app_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) char *envp[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* queue for outgoing uevents */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static LIST_HEAD(smsg_event_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static DEFINE_SPINLOCK(smsg_event_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static void smsg_app_event_free(struct smsg_app_event *ev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) kfree(ev->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) kfree(ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static struct smsg_app_event *smsg_app_event_alloc(const char *from,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) const char *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct smsg_app_event *ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (!ev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ev->buf = kzalloc(ENV_SENDER_LEN + ENV_PREFIX_LEN +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ENV_TEXT_LEN(msg), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!ev->buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) kfree(ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* setting up environment pointers into buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ev->envp[0] = ev->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ev->envp[1] = ev->envp[0] + ENV_SENDER_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ev->envp[2] = ev->envp[1] + ENV_PREFIX_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ev->envp[3] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* setting up environment: sender, prefix name, and message text */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) snprintf(ev->envp[0], ENV_SENDER_LEN, ENV_SENDER_STR "%s", from);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) snprintf(ev->envp[1], ENV_PREFIX_LEN, ENV_PREFIX_STR "%s", SMSG_PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) snprintf(ev->envp[2], ENV_TEXT_LEN(msg), ENV_TEXT_STR "%s", msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static void smsg_event_work_fn(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) LIST_HEAD(event_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct smsg_app_event *p, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dev = get_device(smsg_app_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) spin_lock_bh(&smsg_event_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) list_splice_init(&smsg_event_queue, &event_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) spin_unlock_bh(&smsg_event_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) list_for_each_entry_safe(p, n, &event_queue, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) list_del(&p->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, p->envp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) smsg_app_event_free(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) put_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static DECLARE_WORK(smsg_event_work, smsg_event_work_fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void smsg_app_callback(const char *from, char *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct smsg_app_event *se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* check if the originating z/VM user ID matches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * the configured sender. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (sender && strlen(sender) > 0 && strcmp(from, sender) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* get start of message text (skip prefix and leading blanks) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) msg += strlen(SMSG_PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) while (*msg && isspace(*msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) msg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (*msg == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* allocate event list element and its environment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) se = smsg_app_event_alloc(from, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!se)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* queue event and schedule work function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) spin_lock(&smsg_event_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) list_add_tail(&se->list, &smsg_event_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) spin_unlock(&smsg_event_queue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) schedule_work(&smsg_event_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int __init smsgiucv_app_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct device_driver *smsgiucv_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (!MACHINE_IS_VM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) smsg_app_dev = kzalloc(sizeof(*smsg_app_dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (!smsg_app_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) smsgiucv_drv = driver_find(SMSGIUCV_DRV_NAME, &iucv_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (!smsgiucv_drv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) kfree(smsg_app_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) kfree(smsg_app_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) smsg_app_dev->bus = &iucv_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) smsg_app_dev->parent = iucv_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) smsg_app_dev->release = (void (*)(struct device *)) kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) smsg_app_dev->driver = smsgiucv_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) rc = device_register(smsg_app_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) put_device(smsg_app_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* convert sender to uppercase characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (sender) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int len = strlen(sender);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) while (len--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) sender[len] = toupper(sender[len]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* register with the smsgiucv device driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) device_unregister(smsg_app_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) module_init(smsgiucv_app_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static void __exit smsgiucv_app_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* unregister callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) smsg_unregister_callback(SMSG_PREFIX, smsg_app_callback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* cancel pending work and flush any queued event work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) cancel_work_sync(&smsg_event_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) smsg_event_work_fn(&smsg_event_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) device_unregister(smsg_app_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) module_exit(smsgiucv_app_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) MODULE_DESCRIPTION("Deliver z/VM CP SMSG as uevents");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) MODULE_AUTHOR("Hendrik Brueckner <brueckner@linux.vnet.ibm.com>");