File Index
Files and directories
Sign in
FILE

sclp_ctl.c

File preview with syntax highlighting.

linux-6.19.14/drivers/s390/char/sclp_ctl.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * IOCTL interface for SCLP
  4 *
  5 * Copyright IBM Corp. 2012
  6 *
  7 * Author: Michael Holzheu <holzheu@linux.vnet.ibm.com>
  8 */
  9
 10#include <linux/uaccess.h>
 11#include <linux/miscdevice.h>
 12#include <linux/gfp.h>
 13#include <linux/init.h>
 14#include <linux/ioctl.h>
 15#include <linux/fs.h>
 16#include <asm/sclp_ctl.h>
 17#include <asm/sclp.h>
 18
 19#include "sclp.h"
 20
 21/*
 22 * Supported command words
 23 */
 24static unsigned int sclp_ctl_sccb_wlist[] = {
 25	0x00400002,
 26	0x00410002,
 27};
 28
 29/*
 30 * Check if command word is supported
 31 */
 32static int sclp_ctl_cmdw_supported(unsigned int cmdw)
 33{
 34	int i;
 35
 36	for (i = 0; i < ARRAY_SIZE(sclp_ctl_sccb_wlist); i++) {
 37		if (cmdw == sclp_ctl_sccb_wlist[i])
 38			return 1;
 39	}
 40	return 0;
 41}
 42
 43static void __user *u64_to_uptr(u64 value)
 44{
 45	return (void __user *)(unsigned long)value;
 46}
 47
 48/*
 49 * Start SCLP request
 50 */
 51static int sclp_ctl_ioctl_sccb(void __user *user_area)
 52{
 53	struct sclp_ctl_sccb ctl_sccb;
 54	struct sccb_header *sccb;
 55	unsigned long copied;
 56	int rc;
 57
 58	if (copy_from_user(&ctl_sccb, user_area, sizeof(ctl_sccb)))
 59		return -EFAULT;
 60	if (!sclp_ctl_cmdw_supported(ctl_sccb.cmdw))
 61		return -EOPNOTSUPP;
 62	sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 63	if (!sccb)
 64		return -ENOMEM;
 65	copied = PAGE_SIZE -
 66		copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), PAGE_SIZE);
 67	if (offsetof(struct sccb_header, length) +
 68	    sizeof(sccb->length) > copied || sccb->length > copied) {
 69		rc = -EFAULT;
 70		goto out_free;
 71	}
 72	if (sccb->length < 8) {
 73		rc = -EINVAL;
 74		goto out_free;
 75	}
 76	rc = sclp_sync_request(ctl_sccb.cmdw, sccb);
 77	if (rc)
 78		goto out_free;
 79	if (copy_to_user(u64_to_uptr(ctl_sccb.sccb), sccb, sccb->length))
 80		rc = -EFAULT;
 81out_free:
 82	free_page((unsigned long) sccb);
 83	return rc;
 84}
 85
 86/*
 87 * SCLP SCCB ioctl function
 88 */
 89static long sclp_ctl_ioctl(struct file *filp, unsigned int cmd,
 90			   unsigned long arg)
 91{
 92	void __user *argp;
 93
 94	argp = (void __user *)arg;
 95	switch (cmd) {
 96	case SCLP_CTL_SCCB:
 97		return sclp_ctl_ioctl_sccb(argp);
 98	default: /* unknown ioctl number */
 99		return -ENOTTY;
100	}
101}
102
103/*
104 * File operations
105 */
106static const struct file_operations sclp_ctl_fops = {
107	.owner = THIS_MODULE,
108	.open = nonseekable_open,
109	.unlocked_ioctl = sclp_ctl_ioctl,
110};
111
112/*
113 * Misc device definition
114 */
115static struct miscdevice sclp_ctl_device = {
116	.minor = MISC_DYNAMIC_MINOR,
117	.name = "sclp",
118	.fops = &sclp_ctl_fops,
119};
120builtin_misc_device(sclp_ctl_device);
~/ Read-only file preview.