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: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Родитель
80b054ba2a
Коммит
64150adf89
|
@ -29,6 +29,16 @@ struct chsc_async_area {
|
||||||
__u8 data[CHSC_SIZE - sizeof(struct chsc_async_header)];
|
__u8 data[CHSC_SIZE - sizeof(struct chsc_async_header)];
|
||||||
} __attribute__ ((packed));
|
} __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 {
|
struct chsc_response_struct {
|
||||||
__u16 length;
|
__u16 length;
|
||||||
__u16 code;
|
__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_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_CPD _IOWR(CHSC_IOCTL_MAGIC, 0x87, struct chsc_cpd_info)
|
||||||
#define CHSC_INFO_DCAL _IOWR(CHSC_IOCTL_MAGIC, 0x88, struct chsc_dcal)
|
#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
|
#endif
|
||||||
|
|
|
@ -10,11 +10,6 @@
|
||||||
|
|
||||||
#define CHSC_SDA_OC_MSS 0x2
|
#define CHSC_SDA_OC_MSS 0x2
|
||||||
|
|
||||||
struct chsc_header {
|
|
||||||
u16 length;
|
|
||||||
u16 code;
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
#define NR_MEASUREMENT_CHARS 5
|
#define NR_MEASUREMENT_CHARS 5
|
||||||
struct cmg_chars {
|
struct cmg_chars {
|
||||||
u32 values[NR_MEASUREMENT_CHARS];
|
u32 values[NR_MEASUREMENT_CHARS];
|
||||||
|
|
|
@ -287,11 +287,11 @@ static int chsc_async(struct chsc_async_area *chsc_area,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chsc_log_command(struct chsc_async_area *chsc_area)
|
static void chsc_log_command(void *chsc_area)
|
||||||
{
|
{
|
||||||
char dbf[10];
|
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(0, dbf);
|
||||||
CHSC_LOG_HEX(0, chsc_area, 32);
|
CHSC_LOG_HEX(0, chsc_area, 32);
|
||||||
}
|
}
|
||||||
|
@ -362,6 +362,37 @@ out_free:
|
||||||
return ret;
|
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)
|
static int chsc_ioctl_info_channel_path(void __user *user_cd)
|
||||||
{
|
{
|
||||||
struct chsc_chp_cd *cd;
|
struct chsc_chp_cd *cd;
|
||||||
|
@ -795,6 +826,8 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd,
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case CHSC_START:
|
case CHSC_START:
|
||||||
return chsc_ioctl_start(argp);
|
return chsc_ioctl_start(argp);
|
||||||
|
case CHSC_START_SYNC:
|
||||||
|
return chsc_ioctl_start_sync(argp);
|
||||||
case CHSC_INFO_CHANNEL_PATH:
|
case CHSC_INFO_CHANNEL_PATH:
|
||||||
return chsc_ioctl_info_channel_path(argp);
|
return chsc_ioctl_info_channel_path(argp);
|
||||||
case CHSC_INFO_CU:
|
case CHSC_INFO_CU:
|
||||||
|
|
Загрузка…
Ссылка в новой задаче