Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64150adf authored by Michael Holzheu's avatar Michael Holzheu Committed by Martin Schwidefsky
Browse files

s390/cio: Introduce generic synchronous CHSC IOCTL



This patch adds a new ioctl CHSC_START_SYNC that allows to
execute any synchronous CHSC that is provided by user space.

Signed-off-by: default avatarMichael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 80b054ba
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -29,6 +29,16 @@ struct chsc_async_area {
	__u8 data[CHSC_SIZE - sizeof(struct chsc_async_header)];
} __attribute__ ((packed));

struct chsc_header {
	__u16 length;
	__u16 code;
} __attribute__ ((packed));

struct chsc_sync_area {
	struct chsc_header header;
	__u8 data[CHSC_SIZE - sizeof(struct chsc_header)];
} __attribute__ ((packed));

struct chsc_response_struct {
	__u16 length;
	__u16 code;
@@ -126,5 +136,6 @@ struct chsc_cpd_info {
#define CHSC_INFO_CCL _IOWR(CHSC_IOCTL_MAGIC, 0x86, struct chsc_comp_list)
#define CHSC_INFO_CPD _IOWR(CHSC_IOCTL_MAGIC, 0x87, struct chsc_cpd_info)
#define CHSC_INFO_DCAL _IOWR(CHSC_IOCTL_MAGIC, 0x88, struct chsc_dcal)
#define CHSC_START_SYNC _IOWR(CHSC_IOCTL_MAGIC, 0x89, struct chsc_sync_area)

#endif
+0 −5
Original line number Diff line number Diff line
@@ -10,11 +10,6 @@

#define CHSC_SDA_OC_MSS   0x2

struct chsc_header {
	u16 length;
	u16 code;
} __attribute__ ((packed));

#define NR_MEASUREMENT_CHARS 5
struct cmg_chars {
	u32 values[NR_MEASUREMENT_CHARS];
+35 −2
Original line number Diff line number Diff line
@@ -287,11 +287,11 @@ static int chsc_async(struct chsc_async_area *chsc_area,
	return ret;
}

static void chsc_log_command(struct chsc_async_area *chsc_area)
static void chsc_log_command(void *chsc_area)
{
	char dbf[10];

	sprintf(dbf, "CHSC:%x", chsc_area->header.code);
	sprintf(dbf, "CHSC:%x", ((uint16_t *)chsc_area)[1]);
	CHSC_LOG(0, dbf);
	CHSC_LOG_HEX(0, chsc_area, 32);
}
@@ -362,6 +362,37 @@ static int chsc_ioctl_start(void __user *user_area)
	return ret;
}

static int chsc_ioctl_start_sync(void __user *user_area)
{
	struct chsc_sync_area *chsc_area;
	int ret, ccode;

	chsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
	if (!chsc_area)
		return -ENOMEM;
	if (copy_from_user(chsc_area, user_area, PAGE_SIZE)) {
		ret = -EFAULT;
		goto out_free;
	}
	if (chsc_area->header.code & 0x4000) {
		ret = -EINVAL;
		goto out_free;
	}
	chsc_log_command(chsc_area);
	ccode = chsc(chsc_area);
	if (ccode != 0) {
		ret = -EIO;
		goto out_free;
	}
	if (copy_to_user(user_area, chsc_area, PAGE_SIZE))
		ret = -EFAULT;
	else
		ret = 0;
out_free:
	free_page((unsigned long)chsc_area);
	return ret;
}

static int chsc_ioctl_info_channel_path(void __user *user_cd)
{
	struct chsc_chp_cd *cd;
@@ -795,6 +826,8 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd,
	switch (cmd) {
	case CHSC_START:
		return chsc_ioctl_start(argp);
	case CHSC_START_SYNC:
		return chsc_ioctl_start_sync(argp);
	case CHSC_INFO_CHANNEL_PATH:
		return chsc_ioctl_info_channel_path(argp);
	case CHSC_INFO_CU: