diff options
Diffstat (limited to 'drivers/s390/char')
33 files changed, 326 insertions, 202 deletions
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 8a03af5ee5b3..80c4e5101c97 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig @@ -96,7 +96,7 @@ config SCLP_OFB config S390_UV_UAPI def_tristate m prompt "Ultravisor userspace API" - depends on S390 && (KVM || PROTECTED_VIRTUALIZATION_GUEST) + depends on S390 help Selecting exposes parts of the UV interface to userspace by providing a misc character device at /dev/uv. diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index b0f6b3201636..81d6744e1861 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile @@ -32,7 +32,7 @@ obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o obj-$(CONFIG_PCI) += sclp_pci.o -obj-$(subst m,y,$(CONFIG_ZCRYPT)) += sclp_ap.o +obj-$(subst m,y,$(CONFIG_AP)) += sclp_ap.o obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o obj-$(CONFIG_VMCP) += vmcp.o diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index dcb3c32f027a..6a61c0a595d9 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -23,6 +23,7 @@ #include <linux/reboot.h> #include <linux/serial.h> /* ASYNC_* flags */ #include <linux/slab.h> +#include <asm/machine.h> #include <asm/ccwdev.h> #include <asm/cio.h> #include <linux/io.h> @@ -803,7 +804,6 @@ static struct attribute *con3215_drv_attrs[] = { static struct attribute_group con3215_drv_attr_group = { .attrs = con3215_drv_attrs, - NULL, }; static const struct attribute_group *con3215_drv_attr_groups[] = { @@ -908,7 +908,7 @@ static int __init con3215_init(void) return -ENODEV; /* Set the console mode for VM */ - if (MACHINE_IS_VM) { + if (machine_is_vm()) { cpcmd("TERM CONMODE 3215", NULL, 0, NULL); cpcmd("TERM AUTOCR OFF", NULL, 0, NULL); } diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index 251d2a1c3eef..8402a0042c0d 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c @@ -23,6 +23,7 @@ #include <linux/memblock.h> #include <linux/compat.h> +#include <asm/machine.h> #include <asm/ccwdev.h> #include <asm/cio.h> #include <asm/ebcdic.h> @@ -101,6 +102,7 @@ struct tty3270 { /* Input stuff. */ char *prompt; /* Output string for input area. */ + size_t prompt_sz; /* Size of output string. */ char *input; /* Input string for read request. */ struct raw3270_request *read; /* Single read request. */ struct raw3270_request *kreset; /* Single keyboard reset request. */ @@ -205,7 +207,7 @@ static int tty3270_input_size(int cols) static void tty3270_update_prompt(struct tty3270 *tp, char *input) { - strcpy(tp->prompt, input); + strscpy(tp->prompt, input, tp->prompt_sz); tp->update_flags |= TTY_UPDATE_INPUT; tty3270_set_timer(tp, 1); } @@ -528,7 +530,7 @@ static void tty3270_update(struct timer_list *t) u8 cmd = TC_WRITE; int rc, len; - wrq = xchg(&tp->write, 0); + wrq = xchg(&tp->write, NULL); if (!wrq) { tty3270_set_timer(tp, 1); return; @@ -746,7 +748,7 @@ static void tty3270_issue_read(struct tty3270 *tp, int lock) struct raw3270_request *rrq; int rc; - rrq = xchg(&tp->read, 0); + rrq = xchg(&tp->read, NULL); if (!rrq) /* Read already scheduled. */ return; @@ -792,7 +794,7 @@ static void tty3270_deactivate(struct raw3270_view *view) { struct tty3270 *tp = container_of(view, struct tty3270, view); - del_timer(&tp->timer); + timer_delete(&tp->timer); } static void tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb) @@ -970,6 +972,7 @@ static void tty3270_resize(struct raw3270_view *view, char *old_input, *new_input; struct tty_struct *tty; struct winsize ws; + size_t prompt_sz; int new_allocated, old_allocated = tp->allocated_lines; if (old_model == new_model && @@ -981,10 +984,11 @@ static void tty3270_resize(struct raw3270_view *view, return; } - new_input = kzalloc(tty3270_input_size(new_cols), GFP_KERNEL | GFP_DMA); + prompt_sz = tty3270_input_size(new_cols); + new_input = kzalloc(prompt_sz, GFP_KERNEL | GFP_DMA); if (!new_input) return; - new_prompt = kzalloc(tty3270_input_size(new_cols), GFP_KERNEL); + new_prompt = kzalloc(prompt_sz, GFP_KERNEL); if (!new_prompt) goto out_input; screen = tty3270_alloc_screen(tp, new_rows, new_cols, &new_allocated); @@ -1009,6 +1013,7 @@ static void tty3270_resize(struct raw3270_view *view, old_rcl_lines = tp->rcl_lines; tp->input = new_input; tp->prompt = new_prompt; + tp->prompt_sz = prompt_sz; tp->rcl_lines = new_rcl_lines; tp->rcl_read_index = 0; tp->rcl_write_index = 0; @@ -1059,7 +1064,7 @@ static void tty3270_free(struct raw3270_view *view) { struct tty3270 *tp = container_of(view, struct tty3270, view); - del_timer_sync(&tp->timer); + timer_delete_sync(&tp->timer); tty3270_free_screen(tp->screen, tp->allocated_lines); free_page((unsigned long)tp->converted_line); kfree(tp->input); @@ -1095,6 +1100,7 @@ static int tty3270_create_view(int index, struct tty3270 **newtp) { struct tty3270 *tp; + size_t prompt_sz; int rc; if (tty3270_max_index < index + 1) @@ -1124,17 +1130,19 @@ tty3270_create_view(int index, struct tty3270 **newtp) goto out_free_screen; } - tp->input = kzalloc(tty3270_input_size(tp->view.cols), GFP_KERNEL | GFP_DMA); + prompt_sz = tty3270_input_size(tp->view.cols); + tp->input = kzalloc(prompt_sz, GFP_KERNEL | GFP_DMA); if (!tp->input) { rc = -ENOMEM; goto out_free_converted_line; } - tp->prompt = kzalloc(tty3270_input_size(tp->view.cols), GFP_KERNEL); + tp->prompt = kzalloc(prompt_sz, GFP_KERNEL); if (!tp->prompt) { rc = -ENOMEM; goto out_free_input; } + tp->prompt_sz = prompt_sz; tp->rcl_lines = tty3270_alloc_recall(tp->view.cols); if (!tp->rcl_lines) { @@ -2156,7 +2164,7 @@ con3270_init(void) return -ENODEV; /* Set the console mode for VM */ - if (MACHINE_IS_VM) { + if (machine_is_vm()) { cpcmd("TERM CONMODE 3270", NULL, 0, NULL); cpcmd("TERM AUTOCR OFF", NULL, 0, NULL); } @@ -2185,6 +2193,7 @@ con3270_init(void) console_initcall(con3270_init); #endif +MODULE_DESCRIPTION("IBM/3270 Driver - tty functions"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(IBM_TTY3270_MAJOR); diff --git a/drivers/s390/char/diag_ftp.c b/drivers/s390/char/diag_ftp.c index 9418a9270d03..f41b39c9d267 100644 --- a/drivers/s390/char/diag_ftp.c +++ b/drivers/s390/char/diag_ftp.c @@ -106,7 +106,7 @@ static int diag_ftp_2c4(struct diag_ftp_ldfpl *fpl, int rc; diag_stat_inc(DIAG_STAT_X2C4); - asm volatile( + asm_inline volatile( " diag %[addr],%[cmd],0x2c4\n" "0: j 2f\n" "1: la %[rc],%[err]\n" @@ -159,7 +159,7 @@ ssize_t diag_ftp_cmd(const struct hmcdrv_ftp_cmdspec *ftp, size_t *fsize) goto out; } - len = strscpy(ldfpl->fident, ftp->fname, sizeof(ldfpl->fident)); + len = strscpy(ldfpl->fident, ftp->fname); if (len < 0) { len = -EINVAL; goto out_free; diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 4d824f86bbbb..cfe7efd5b5da 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -515,7 +515,6 @@ static const struct file_operations fs3270_fops = { .compat_ioctl = fs3270_ioctl, /* ioctl */ .open = fs3270_open, /* open */ .release = fs3270_close, /* release */ - .llseek = no_llseek, }; static void fs3270_create_cb(int minor) @@ -559,6 +558,7 @@ static void __exit fs3270_exit(void) __unregister_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270"); } +MODULE_DESCRIPTION("IBM/3270 Driver - fullscreen driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(IBM_FS3270_MAJOR); diff --git a/drivers/s390/char/hmcdrv_dev.c b/drivers/s390/char/hmcdrv_dev.c index 8d50c894711f..e069dd685899 100644 --- a/drivers/s390/char/hmcdrv_dev.c +++ b/drivers/s390/char/hmcdrv_dev.c @@ -186,9 +186,6 @@ static loff_t hmcdrv_dev_seek(struct file *fp, loff_t pos, int whence) if (pos < 0) return -EINVAL; - if (fp->f_pos != pos) - ++fp->f_version; - fp->f_pos = pos; return pos; } diff --git a/drivers/s390/char/hmcdrv_ftp.c b/drivers/s390/char/hmcdrv_ftp.c index 02b6f394aec2..4e3c7ec6749b 100644 --- a/drivers/s390/char/hmcdrv_ftp.c +++ b/drivers/s390/char/hmcdrv_ftp.c @@ -17,6 +17,8 @@ #include <linux/ctype.h> #include <linux/crc16.h> +#include <asm/machine.h> + #include "hmcdrv_ftp.h" #include "hmcdrv_cache.h" #include "sclp_ftp.h" @@ -308,9 +310,9 @@ int hmcdrv_ftp_startup(void) mutex_lock(&hmcdrv_ftp_mutex); /* block transfers while start-up */ if (hmcdrv_ftp_refcnt == 0) { - if (MACHINE_IS_VM) + if (machine_is_vm()) hmcdrv_ftp_funcs = &hmcdrv_ftp_zvm; - else if (MACHINE_IS_LPAR || MACHINE_IS_KVM) + else if (machine_is_lpar() || machine_is_kvm()) hmcdrv_ftp_funcs = &hmcdrv_ftp_lpar; else rc = -EOPNOTSUPP; diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 7207a7f5842a..2d9886651d9b 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c @@ -24,6 +24,7 @@ #include <linux/slab.h> #include <net/iucv/iucv.h> #include <linux/uaccess.h> +#include <asm/machine.h> #include <asm/ebcdic.h> #include <asm/extmem.h> @@ -456,7 +457,7 @@ static int __init mon_init(void) { int rc; - if (!MACHINE_IS_VM) { + if (!machine_is_vm()) { pr_err("The z/VM *MONITOR record device driver cannot be " "loaded without z/VM\n"); return -ENODEV; diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index bc5193d81f9c..0fab1f025a94 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c @@ -23,6 +23,7 @@ #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/io.h> +#include <asm/machine.h> #include <asm/ebcdic.h> #include <asm/appldata.h> #include <asm/monwriter.h> @@ -293,7 +294,7 @@ static struct miscdevice mon_dev = { static int __init mon_init(void) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return -ENODEV; /* * misc_register() has to be the last action in module_init(), because diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 37173cb0f5f5..d2ce7f80ae8d 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -17,6 +17,7 @@ #include <linux/types.h> #include <linux/wait.h> +#include <asm/machine.h> #include <asm/ccwdev.h> #include <asm/cio.h> #include <asm/ebcdic.h> @@ -162,7 +163,8 @@ struct raw3270_request *raw3270_request_alloc(size_t size) /* * Setup ccw. */ - rq->ccw.cda = virt_to_dma32(rq->buffer); + if (rq->buffer) + rq->ccw.cda = virt_to_dma32(rq->buffer); rq->ccw.flags = CCW_FLAG_SLI; return rq; @@ -188,7 +190,8 @@ int raw3270_request_reset(struct raw3270_request *rq) return -EBUSY; rq->ccw.cmd_code = 0; rq->ccw.count = 0; - rq->ccw.cda = virt_to_dma32(rq->buffer); + if (rq->buffer) + rq->ccw.cda = virt_to_dma32(rq->buffer); rq->ccw.flags = CCW_FLAG_SLI; rq->rescnt = 0; rq->rc = 0; @@ -616,7 +619,7 @@ static void raw3270_reset_device_cb(struct raw3270_request *rq, void *data) if (rq->rc) { /* Reset command failed. */ rp->state = RAW3270_STATE_INIT; - } else if (MACHINE_IS_VM) { + } else if (machine_is_vm()) { raw3270_size_device_vm(rp); raw3270_size_device_done(rp); } else { @@ -1339,6 +1342,7 @@ static void raw3270_exit(void) class_unregister(&class3270); } +MODULE_DESCRIPTION("IBM/3270 Driver - core functions"); MODULE_LICENSE("GPL"); module_init(raw3270_init); diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index d53ee34d398f..840be75e75d4 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -245,7 +245,6 @@ static void sclp_request_timeout(bool force_restart); static void sclp_process_queue(void); static void __sclp_make_read_req(void); static int sclp_init_mask(int calculate); -static int sclp_init(void); static void __sclp_queue_read_req(void) @@ -262,7 +261,7 @@ __sclp_queue_read_req(void) static inline void __sclp_set_request_timer(unsigned long time, void (*cb)(struct timer_list *)) { - del_timer(&sclp_request_timer); + timer_delete(&sclp_request_timer); sclp_request_timer.function = cb; sclp_request_timer.expires = jiffies + time; add_timer(&sclp_request_timer); @@ -408,7 +407,7 @@ __sclp_start_request(struct sclp_req *req) if (sclp_running_state != sclp_running_state_idle) return 0; - del_timer(&sclp_request_timer); + timer_delete(&sclp_request_timer); rc = sclp_service_call_trace(req->command, req->sccb); req->start_count++; @@ -443,7 +442,7 @@ sclp_process_queue(void) spin_unlock_irqrestore(&sclp_lock, flags); return; } - del_timer(&sclp_request_timer); + timer_delete(&sclp_request_timer); while (!list_empty(&sclp_req_queue)) { req = list_entry(sclp_req_queue.next, struct sclp_req, list); rc = __sclp_start_request(req); @@ -663,7 +662,7 @@ static void sclp_interrupt_handler(struct ext_code ext_code, !ok_response(finished_sccb, active_cmd)); if (finished_sccb) { - del_timer(&sclp_request_timer); + timer_delete(&sclp_request_timer); sclp_running_state = sclp_running_state_reset_pending; req = __sclp_find_req(finished_sccb); if (req) { @@ -736,11 +735,11 @@ sclp_sync_wait(void) cr0_sync.val = cr0.val & ~CR0_IRQ_SUBCLASS_MASK; cr0_sync.val |= 1UL << (63 - 54); local_ctl_load(0, &cr0_sync); - __arch_local_irq_stosm(0x01); + arch_local_irq_enable_external(); /* Loop until driver state indicates finished request */ while (sclp_running_state != sclp_running_state_idle) { /* Check for expired request timer */ - if (get_tod_clock_fast() > timeout && del_timer(&sclp_request_timer)) + if (get_tod_clock_fast() > timeout && timer_delete(&sclp_request_timer)) sclp_request_timer.function(&sclp_request_timer); cpu_relax(); } @@ -1166,7 +1165,7 @@ sclp_check_interface(void) * with IRQs enabled. */ irq_subclass_unregister(IRQ_SUBCLASS_SERVICE_SIGNAL); spin_lock_irqsave(&sclp_lock, flags); - del_timer(&sclp_request_timer); + timer_delete(&sclp_request_timer); rc = -EBUSY; if (sclp_init_req.status == SCLP_REQ_DONE) { if (sccb->header.response_code == 0x20) { @@ -1195,7 +1194,8 @@ sclp_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) } static struct notifier_block sclp_reboot_notifier = { - .notifier_call = sclp_reboot_event + .notifier_call = sclp_reboot_event, + .priority = INT_MIN, }; static ssize_t con_pages_show(struct device_driver *dev, char *buf) @@ -1250,8 +1250,7 @@ static struct platform_driver sclp_pdrv = { /* Initialize SCLP driver. Return zero if driver is operational, non-zero * otherwise. */ -static int -sclp_init(void) +int sclp_init(void) { unsigned long flags; int rc = 0; @@ -1293,6 +1292,7 @@ sclp_init(void) fail_unregister_reboot_notifier: unregister_reboot_notifier(&sclp_reboot_notifier); fail_init_state_uninitialized: + list_del(&sclp_state_change_event.list); sclp_init_state = sclp_init_state_uninitialized; free_page((unsigned long) sclp_read_sccb); free_page((unsigned long) sclp_init_sccb); @@ -1303,13 +1303,7 @@ fail_unlock: static __init int sclp_initcall(void) { - int rc; - - rc = platform_driver_register(&sclp_pdrv); - if (rc) - return rc; - - return sclp_init(); + return platform_driver_register(&sclp_pdrv); } arch_initcall(sclp_initcall); diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 6a23ec286c70..b31a680e0871 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -12,8 +12,10 @@ #include <linux/types.h> #include <linux/list.h> #include <asm/asm-extable.h> +#include <asm/machine.h> #include <asm/sclp.h> #include <asm/ebcdic.h> +#include <asm/asm.h> /* maximum number of pages concerning our own memory management */ #define MAX_KMEM_PAGES (sizeof(unsigned long) << 3) @@ -84,13 +86,6 @@ typedef unsigned int sclp_cmdw_t; typedef u64 sccb_mask_t; -struct sccb_header { - u16 length; - u8 function_code; - u8 control_mask[3]; - u16 response_code; -} __attribute__((packed)); - struct init_sccb { struct sccb_header header; u16 _reserved; @@ -195,7 +190,9 @@ struct read_info_sccb { u8 byte_134; /* 134 */ u8 cpudirq; /* 135 */ u16 cbl; /* 136-137 */ - u8 _pad_138[EXT_SCCB_READ_SCP - 138]; + u8 byte_138; /* 138 */ + u8 byte_139; /* 139 */ + u8 _pad_140[EXT_SCCB_READ_SCP - 140]; } __packed __aligned(PAGE_SIZE); struct read_storage_sccb { @@ -237,13 +234,6 @@ struct gds_vector { u16 gds_id; } __attribute__((packed)); -struct evbuf_header { - u16 length; - u8 type; - u8 flags; - u16 _reserved; -} __attribute__((packed)); - struct sclp_req { struct list_head list; /* list_head for request queueing. */ sclp_cmdw_t command; /* sclp command to execute */ @@ -325,19 +315,22 @@ struct read_info_sccb * __init sclp_early_get_info(void); /* Perform service call. Return 0 on success, non-zero otherwise. */ static inline int sclp_service_call(sclp_cmdw_t command, void *sccb) { - int cc = 4; /* Initialize for program check handling */ + int cc, exception; - asm volatile( - "0: .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */ - "1: ipm %0\n" - " srl %0,28\n" + exception = 1; + asm_inline volatile( + "0: .insn rre,0xb2200000,%[cmd],%[sccb]\n" /* servc */ + "1: lhi %[exc],0\n" "2:\n" + CC_IPM(cc) EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : "+&d" (cc) : "d" (command), "a" (__pa(sccb)) - : "cc", "memory"); - if (cc == 4) + : CC_OUT(cc, cc), [exc] "+d" (exception) + : [cmd] "d" (command), [sccb] "a" (__pa(sccb)) + : CC_CLOBBER_LIST("memory")); + if (exception) return -EINVAL; + cc = CC_TRANSFORM(cc); if (cc == 3) return -EIO; if (cc == 2) @@ -350,21 +343,21 @@ static inline int sclp_service_call(sclp_cmdw_t command, void *sccb) static inline unsigned char sclp_ascebc(unsigned char ch) { - return (MACHINE_IS_VM) ? _ascebc[ch] : _ascebc_500[ch]; + return (machine_is_vm()) ? _ascebc[ch] : _ascebc_500[ch]; } /* translate string from EBCDIC to ASCII */ static inline void sclp_ebcasc_str(char *str, int nr) { - (MACHINE_IS_VM) ? EBCASC(str, nr) : EBCASC_500(str, nr); + (machine_is_vm()) ? EBCASC(str, nr) : EBCASC_500(str, nr); } /* translate string from ASCII to EBCDIC */ static inline void sclp_ascebc_str(char *str, int nr) { - (MACHINE_IS_VM) ? ASCEBC(str, nr) : ASCEBC_500(str, nr); + (machine_is_vm()) ? ASCEBC(str, nr) : ASCEBC_500(str, nr); } static inline struct gds_vector * diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 7815e9bea69a..9fcdce9bb35f 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -8,6 +8,7 @@ #define KMSG_COMPONENT "sclp_cmd" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include <linux/cpufeature.h> #include <linux/completion.h> #include <linux/init.h> #include <linux/errno.h> @@ -31,6 +32,9 @@ #include "sclp.h" +#define SCLP_CMDW_ASSIGN_STORAGE 0x000d0001 +#define SCLP_CMDW_UNASSIGN_STORAGE 0x000c0001 + static void sclp_sync_callback(struct sclp_req *req, void *data) { struct completion *completion = data; @@ -225,7 +229,7 @@ static int sclp_assign_storage(u16 rn) unsigned long long start; int rc; - rc = do_assign_storage(0x000d0001, rn); + rc = do_assign_storage(SCLP_CMDW_ASSIGN_STORAGE, rn); if (rc) return rc; start = rn2addr(rn); @@ -235,7 +239,7 @@ static int sclp_assign_storage(u16 rn) static int sclp_unassign_storage(u16 rn) { - return do_assign_storage(0x000c0001, rn); + return do_assign_storage(SCLP_CMDW_UNASSIGN_STORAGE, rn); } struct attach_storage_sccb { @@ -425,7 +429,7 @@ static void __init add_memory_merged(u16 rn) goto skip_add; for (addr = start; addr < start + size; addr += block_size) add_memory(0, addr, block_size, - MACHINE_HAS_EDAT1 ? + cpu_has_edat1() ? MHP_MEMMAP_ON_MEMORY | MHP_OFFLINE_INACCESSIBLE : MHP_NONE); skip_add: first_rn = rn; diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index e5d947c763ea..d8544c485808 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c @@ -109,7 +109,7 @@ static void sclp_console_sync_queue(void) unsigned long flags; spin_lock_irqsave(&sclp_con_lock, flags); - del_timer(&sclp_con_timer); + timer_delete(&sclp_con_timer); while (sclp_con_queue_running) { spin_unlock_irqrestore(&sclp_con_lock, flags); sclp_sync_wait(); @@ -264,6 +264,19 @@ static struct console sclp_console = }; /* + * Release allocated pages. + */ +static void __init __sclp_console_free_pages(void) +{ + struct list_head *page, *p; + + list_for_each_safe(page, p, &sclp_con_pages) { + list_del(page); + free_page((unsigned long)page); + } +} + +/* * called by console_init() in drivers/char/tty_io.c at boot-time. */ static int __init @@ -282,6 +295,10 @@ sclp_console_init(void) /* Allocate pages for output buffering */ for (i = 0; i < sclp_console_pages; i++) { page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!page) { + __sclp_console_free_pages(); + return -ENOMEM; + } list_add_tail(page, &sclp_con_pages); } sclp_conbuf = NULL; diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c index 10383e936461..ae5d28987177 100644 --- a/drivers/s390/char/sclp_config.c +++ b/drivers/s390/char/sclp_config.c @@ -60,7 +60,7 @@ static void sclp_cpu_capability_notify(struct work_struct *work) static void __ref sclp_cpu_change_notify(struct work_struct *work) { lock_device_hotplug(); - smp_rescan_cpus(); + smp_rescan_cpus(false); unlock_device_hotplug(); } @@ -128,7 +128,7 @@ out: } static ssize_t sysfs_ofb_data_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, + const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { int rc; @@ -142,7 +142,7 @@ static const struct bin_attribute ofb_bin_attr = { .name = "event_data", .mode = S_IWUSR, }, - .write = sysfs_ofb_data_write, + .write_new = sysfs_ofb_data_write, }; #endif diff --git a/drivers/s390/char/sclp_cpi_sys.c b/drivers/s390/char/sclp_cpi_sys.c index f60d7ea8268d..d8f91aab11e8 100644 --- a/drivers/s390/char/sclp_cpi_sys.c +++ b/drivers/s390/char/sclp_cpi_sys.c @@ -223,7 +223,7 @@ static ssize_t system_name_show(struct kobject *kobj, int rc; mutex_lock(&sclp_cpi_mutex); - rc = snprintf(page, PAGE_SIZE, "%s\n", system_name); + rc = sysfs_emit(page, "%s\n", system_name); mutex_unlock(&sclp_cpi_mutex); return rc; } @@ -255,7 +255,7 @@ static ssize_t sysplex_name_show(struct kobject *kobj, int rc; mutex_lock(&sclp_cpi_mutex); - rc = snprintf(page, PAGE_SIZE, "%s\n", sysplex_name); + rc = sysfs_emit(page, "%s\n", sysplex_name); mutex_unlock(&sclp_cpi_mutex); return rc; } @@ -287,7 +287,7 @@ static ssize_t system_type_show(struct kobject *kobj, int rc; mutex_lock(&sclp_cpi_mutex); - rc = snprintf(page, PAGE_SIZE, "%s\n", system_type); + rc = sysfs_emit(page, "%s\n", system_type); mutex_unlock(&sclp_cpi_mutex); return rc; } @@ -321,7 +321,7 @@ static ssize_t system_level_show(struct kobject *kobj, mutex_lock(&sclp_cpi_mutex); level = system_level; mutex_unlock(&sclp_cpi_mutex); - return snprintf(page, PAGE_SIZE, "%#018llx\n", level); + return sysfs_emit(page, "%#018llx\n", level); } static ssize_t system_level_store(struct kobject *kobj, diff --git a/drivers/s390/char/sclp_ctl.c b/drivers/s390/char/sclp_ctl.c index 248b5db3eaa8..dd6051602070 100644 --- a/drivers/s390/char/sclp_ctl.c +++ b/drivers/s390/char/sclp_ctl.c @@ -115,7 +115,6 @@ static const struct file_operations sclp_ctl_fops = { .open = nonseekable_open, .unlocked_ioctl = sclp_ctl_ioctl, .compat_ioctl = sclp_ctl_ioctl, - .llseek = no_llseek, }; /* diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index 60a247fdb2a7..93b2d20d720c 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -44,15 +44,14 @@ static void __init sclp_early_facilities_detect(void) sclp.has_ibs = !!(sccb->fac117 & 0x20); sclp.has_gisaf = !!(sccb->fac118 & 0x08); sclp.has_hvs = !!(sccb->fac119 & 0x80); + sclp.has_wti = !!(sccb->fac119 & 0x40); sclp.has_kss = !!(sccb->fac98 & 0x01); sclp.has_aisii = !!(sccb->fac118 & 0x40); sclp.has_aeni = !!(sccb->fac118 & 0x20); sclp.has_aisi = !!(sccb->fac118 & 0x10); sclp.has_zpci_lsi = !!(sccb->fac118 & 0x01); - if (sccb->fac85 & 0x02) - S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; - if (sccb->fac91 & 0x40) - S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST; + sclp.has_diag204_bif = !!(sccb->fac98 & 0x80); + sclp.has_diag310 = !!(sccb->fac91 & 0x80); if (sccb->cpuoff > 134) { sclp.has_diag318 = !!(sccb->byte_134 & 0x80); sclp.has_diag320 = !!(sccb->byte_134 & 0x04); @@ -62,6 +61,8 @@ static void __init sclp_early_facilities_detect(void) sclp.has_sipl = !!(sccb->cbl & 0x4000); sclp.has_sipl_eckd = !!(sccb->cbl & 0x2000); } + if (sccb->cpuoff > 139) + sclp.has_diag324 = !!(sccb->byte_139 & 0x80); sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; sclp.rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; sclp.rzm <<= 20; @@ -73,7 +74,7 @@ static void __init sclp_early_facilities_detect(void) sclp.hamax = U64_MAX; if (!sccb->hcpua) { - if (MACHINE_IS_VM) + if (machine_is_vm()) sclp.max_cores = 64; else sclp.max_cores = sccb->ncpurl; diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c index 9f6165cafdc3..b5bd40f13c75 100644 --- a/drivers/s390/char/sclp_early_core.c +++ b/drivers/s390/char/sclp_early_core.c @@ -13,6 +13,7 @@ #include <asm/sections.h> #include <asm/physmem_info.h> #include <asm/facility.h> +#include <asm/machine.h> #include "sclp.h" #include "sclp_rw.h" @@ -38,11 +39,11 @@ void sclp_early_wait_irq(void) cr0_new.sssm = 1; local_ctl_load(0, &cr0_new.reg); - psw_ext_save = S390_lowcore.external_new_psw; + psw_ext_save = get_lowcore()->external_new_psw; psw_mask = __extract_psw(); - S390_lowcore.external_new_psw.mask = psw_mask; + get_lowcore()->external_new_psw.mask = psw_mask; psw_wait.mask = psw_mask | PSW_MASK_EXT | PSW_MASK_WAIT; - S390_lowcore.ext_int_code = 0; + get_lowcore()->ext_int_code = 0; do { asm volatile( @@ -53,12 +54,12 @@ void sclp_early_wait_irq(void) "0:\n" : [addr] "=&d" (addr), [psw_wait_addr] "=Q" (psw_wait.addr), - [psw_ext_addr] "=Q" (S390_lowcore.external_new_psw.addr) + [psw_ext_addr] "=Q" (get_lowcore()->external_new_psw.addr) : [psw_wait] "Q" (psw_wait) : "cc", "memory"); - } while (S390_lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG); + } while (get_lowcore()->ext_int_code != EXT_IRQ_SERVICE_SIG); - S390_lowcore.external_new_psw = psw_ext_save; + get_lowcore()->external_new_psw = psw_ext_save; local_ctl_load(0, &cr0.reg); } @@ -335,6 +336,18 @@ int __init sclp_early_get_hsa_size(unsigned long *hsa_size) return 0; } +void __init sclp_early_detect_machine_features(void) +{ + struct read_info_sccb *sccb = &sclp_info_sccb; + + if (!sclp_info_sccb_valid) + return; + if (sccb->fac85 & 0x02) + set_machine_feature(MFEATURE_ESOP); + if (sccb->fac91 & 0x40) + set_machine_feature(MFEATURE_TLB_GUEST); +} + #define SCLP_STORAGE_INFO_FACILITY 0x0000400000000000UL void __weak __init add_physmem_online_range(u64 start, u64 end) {} diff --git a/drivers/s390/char/sclp_ocf.c b/drivers/s390/char/sclp_ocf.c index d35f10ea5b52..ca6c5260dc53 100644 --- a/drivers/s390/char/sclp_ocf.c +++ b/drivers/s390/char/sclp_ocf.c @@ -101,7 +101,7 @@ static ssize_t cpc_name_show(struct kobject *kobj, sclp_ocf_cpc_name_copy(name); name[OCF_LENGTH_CPC_NAME] = 0; EBCASC(name, OCF_LENGTH_CPC_NAME); - return snprintf(page, PAGE_SIZE, "%s\n", name); + return sysfs_emit(page, "%s\n", name); } static struct kobj_attribute cpc_name_attr = @@ -113,7 +113,7 @@ static ssize_t hmc_network_show(struct kobject *kobj, int rc; spin_lock_irq(&sclp_ocf_lock); - rc = snprintf(page, PAGE_SIZE, "%s\n", hmc_network); + rc = sysfs_emit(page, "%s\n", hmc_network); spin_unlock_irq(&sclp_ocf_lock); return rc; } diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c index a3e5a5fb0c1e..56400886f7fc 100644 --- a/drivers/s390/char/sclp_pci.c +++ b/drivers/s390/char/sclp_pci.c @@ -24,29 +24,11 @@ #define SCLP_ATYPE_PCI 2 -#define SCLP_ERRNOTIFY_AQ_RESET 0 -#define SCLP_ERRNOTIFY_AQ_REPAIR 1 -#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2 - static DEFINE_MUTEX(sclp_pci_mutex); static struct sclp_register sclp_pci_event = { .send_mask = EVTYP_ERRNOTIFY_MASK, }; -struct err_notify_evbuf { - struct evbuf_header header; - u8 action; - u8 atype; - u32 fh; - u32 fid; - u8 data[]; -} __packed; - -struct err_notify_sccb { - struct sccb_header header; - struct err_notify_evbuf evbuf; -} __packed; - struct pci_cfg_sccb { struct sccb_header header; u8 atype; /* adapter type */ @@ -116,6 +98,7 @@ static int sclp_pci_check_report(struct zpci_report_error_header *report) case SCLP_ERRNOTIFY_AQ_RESET: case SCLP_ERRNOTIFY_AQ_REPAIR: case SCLP_ERRNOTIFY_AQ_INFO_LOG: + case SCLP_ERRNOTIFY_AQ_OPTICS_DATA: break; default: return -EINVAL; diff --git a/drivers/s390/char/sclp_sd.c b/drivers/s390/char/sclp_sd.c index f9e164be7568..8524c14affed 100644 --- a/drivers/s390/char/sclp_sd.c +++ b/drivers/s390/char/sclp_sd.c @@ -9,6 +9,7 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/completion.h> +#include <linux/jiffies.h> #include <linux/kobject.h> #include <linux/list.h> #include <linux/printk.h> @@ -28,6 +29,8 @@ #define SD_DI_CONFIG 3 +#define SD_TIMEOUT msecs_to_jiffies(30000) + struct sclp_sd_evbuf { struct evbuf_header hdr; u8 eq; @@ -194,6 +197,10 @@ static int sclp_sd_sync(unsigned long page, u8 eq, u8 di, u64 sat, u64 sa, struct sclp_sd_evbuf *evbuf; int rc; + if (!sclp_sd_register.sclp_send_mask || + !sclp_sd_register.sclp_receive_mask) + return -EIO; + sclp_sd_listener_init(&listener, __pa(sccb)); sclp_sd_listener_add(&listener); @@ -230,9 +237,12 @@ static int sclp_sd_sync(unsigned long page, u8 eq, u8 di, u64 sat, u64 sa, goto out; } if (!(evbuf->rflags & 0x80)) { - rc = wait_for_completion_interruptible(&listener.completion); - if (rc) + rc = wait_for_completion_interruptible_timeout(&listener.completion, SD_TIMEOUT); + if (rc == 0) + rc = -ETIME; + if (rc < 0) goto out; + rc = 0; evbuf = &listener.evbuf; } switch (evbuf->status) { @@ -319,9 +329,15 @@ static int sclp_sd_store_data(struct sclp_sd_data *result, u8 di) rc = sclp_sd_sync(page, SD_EQ_STORE_DATA, di, asce, (u64) data, &dsize, &esize); if (rc) { - /* Cancel running request if interrupted */ - if (rc == -ERESTARTSYS) - sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL); + /* Cancel running request if interrupted or timed out */ + if (rc == -ERESTARTSYS || rc == -ETIME) { + if (sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL)) { + pr_warn("Could not stop Store Data request - leaking at least %zu bytes\n", + (size_t)dsize * PAGE_SIZE); + data = NULL; + asce = 0; + } + } vfree(data); goto out; } @@ -460,7 +476,7 @@ static struct kobj_type sclp_sd_file_ktype = { * on EOF. */ static ssize_t data_read(struct file *file, struct kobject *kobj, - struct bin_attribute *attr, char *buffer, + const struct bin_attribute *attr, char *buffer, loff_t off, size_t size) { struct sclp_sd_file *sd_file = to_sd_file(kobj); @@ -523,7 +539,7 @@ static __init struct sclp_sd_file *sclp_sd_file_create(const char *name, u8 di) sysfs_bin_attr_init(&sd_file->data_attr); sd_file->data_attr.attr.name = "data"; sd_file->data_attr.attr.mode = 0444; - sd_file->data_attr.read = data_read; + sd_file->data_attr.read_new = data_read; rc = sysfs_create_bin_file(&sd_file->kobj, &sd_file->data_attr); if (rc) { diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 892c18d2f87e..0a92d08830e7 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -490,6 +490,17 @@ static const struct tty_operations sclp_ops = { .flush_buffer = sclp_tty_flush_buffer, }; +/* Release allocated pages. */ +static void __init __sclp_tty_free_pages(void) +{ + struct list_head *page, *p; + + list_for_each_safe(page, p, &sclp_tty_pages) { + list_del(page); + free_page((unsigned long)page); + } +} + static int __init sclp_tty_init(void) { @@ -499,7 +510,7 @@ sclp_tty_init(void) int rc; /* z/VM multiplexes the line mode output on the 32xx screen */ - if (MACHINE_IS_VM && !CONSOLE_IS_SCLP) + if (machine_is_vm() && !CONSOLE_IS_SCLP) return 0; if (!sclp.has_linemode) return 0; @@ -516,6 +527,7 @@ sclp_tty_init(void) for (i = 0; i < MAX_KMEM_PAGES; i++) { page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); if (page == NULL) { + __sclp_tty_free_pages(); tty_driver_kref_put(driver); return -ENOMEM; } @@ -524,7 +536,7 @@ sclp_tty_init(void) timer_setup(&sclp_tty_timer, sclp_tty_timeout, 0); sclp_ttybuf = NULL; sclp_tty_buffer_count = 0; - if (MACHINE_IS_VM) { + if (machine_is_vm()) { /* case input lines to lowercase */ sclp_tty_tolower = 1; } diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 218ae604f737..62979adcb381 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -231,7 +231,7 @@ sclp_vt220_emit_current(void) list_add_tail(&sclp_vt220_current_request->list, &sclp_vt220_outqueue); sclp_vt220_current_request = NULL; - del_timer(&sclp_vt220_timer); + timer_delete(&sclp_vt220_timer); } sclp_vt220_flush_later = 0; } @@ -319,7 +319,7 @@ sclp_vt220_add_msg(struct sclp_vt220_request *request, buffer = (void *) ((addr_t) sccb + sccb->header.length); if (convertlf) { - /* Perform Linefeed conversion (0x0a -> 0x0a 0x0d)*/ + /* Perform Linefeed conversion (0x0a -> 0x0d 0x0a)*/ for (from=0, to=0; (from < count) && (to < sclp_vt220_space_left(request)); from++) { @@ -328,8 +328,8 @@ sclp_vt220_add_msg(struct sclp_vt220_request *request, /* Perform conversion */ if (c == 0x0a) { if (to + 1 < sclp_vt220_space_left(request)) { - ((unsigned char *) buffer)[to++] = c; ((unsigned char *) buffer)[to++] = 0x0d; + ((unsigned char *) buffer)[to++] = c; } else break; @@ -798,7 +798,7 @@ sclp_vt220_notify(struct notifier_block *self, sclp_vt220_emit_current(); spin_lock_irqsave(&sclp_vt220_lock, flags); - del_timer(&sclp_vt220_timer); + timer_delete(&sclp_vt220_timer); while (sclp_vt220_queue_running) { spin_unlock_irqrestore(&sclp_vt220_lock, flags); sclp_sync_wait(); diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index cc8237afeffa..89778d922d9f 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -52,7 +52,6 @@ static const struct file_operations tape_fops = #endif .open = tapechar_open, .release = tapechar_release, - .llseek = no_llseek, }; static int tapechar_major = TAPECHAR_MAJOR; diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index a6d2a4792185..48e8417a5cff 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -96,7 +96,7 @@ tape_medium_state_show(struct device *dev, struct device_attribute *attr, char * struct tape_device *tdev; tdev = dev_get_drvdata(dev); - return scnprintf(buf, PAGE_SIZE, "%i\n", tdev->medium_state); + return sysfs_emit(buf, "%i\n", tdev->medium_state); } static @@ -108,7 +108,7 @@ tape_first_minor_show(struct device *dev, struct device_attribute *attr, char *b struct tape_device *tdev; tdev = dev_get_drvdata(dev); - return scnprintf(buf, PAGE_SIZE, "%i\n", tdev->first_minor); + return sysfs_emit(buf, "%i\n", tdev->first_minor); } static @@ -120,8 +120,8 @@ tape_state_show(struct device *dev, struct device_attribute *attr, char *buf) struct tape_device *tdev; tdev = dev_get_drvdata(dev); - return scnprintf(buf, PAGE_SIZE, "%s\n", (tdev->first_minor < 0) ? - "OFFLINE" : tape_state_verbose[tdev->tape_state]); + return sysfs_emit(buf, "%s\n", (tdev->first_minor < 0) ? + "OFFLINE" : tape_state_verbose[tdev->tape_state]); } static @@ -135,17 +135,17 @@ tape_operation_show(struct device *dev, struct device_attribute *attr, char *buf tdev = dev_get_drvdata(dev); if (tdev->first_minor < 0) - return scnprintf(buf, PAGE_SIZE, "N/A\n"); + return sysfs_emit(buf, "N/A\n"); spin_lock_irq(get_ccwdev_lock(tdev->cdev)); if (list_empty(&tdev->req_queue)) - rc = scnprintf(buf, PAGE_SIZE, "---\n"); + rc = sysfs_emit(buf, "---\n"); else { struct tape_request *req; req = list_entry(tdev->req_queue.next, struct tape_request, list); - rc = scnprintf(buf,PAGE_SIZE, "%s\n", tape_op_verbose[req->op]); + rc = sysfs_emit(buf, "%s\n", tape_op_verbose[req->op]); } spin_unlock_irq(get_ccwdev_lock(tdev->cdev)); return rc; @@ -161,7 +161,7 @@ tape_blocksize_show(struct device *dev, struct device_attribute *attr, char *buf tdev = dev_get_drvdata(dev); - return scnprintf(buf, PAGE_SIZE, "%i\n", tdev->char_data.block_size); + return sysfs_emit(buf, "%i\n", tdev->char_data.block_size); } static @@ -1108,7 +1108,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) struct tape_request, list); if (req->status == TAPE_REQUEST_LONG_BUSY) { DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id); - if (del_timer(&device->lb_timeout)) { + if (timer_delete(&device->lb_timeout)) { tape_put_device(device); __tape_start_next_request(device); } diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index f7e75d9fedf6..b76038632883 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c @@ -73,7 +73,7 @@ tape_std_assign(struct tape_device *device) rc = tape_do_io_interruptible(device, request); - del_timer_sync(&request->timer); + timer_delete_sync(&request->timer); if (rc != 0) { DBF_EVENT(3, "%08x: assign failed - device might be busy\n", diff --git a/drivers/s390/char/uvdevice.c b/drivers/s390/char/uvdevice.c index 42c9f77f8da0..2b83fb6dc1d7 100644 --- a/drivers/s390/char/uvdevice.c +++ b/drivers/s390/char/uvdevice.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright IBM Corp. 2022 + * Copyright IBM Corp. 2022, 2024 * Author(s): Steffen Eiden <seiden@linux.ibm.com> * * This file provides a Linux misc device to give userspace access to some @@ -40,6 +40,7 @@ static const u32 ioctl_nr_to_uvc_bit[] __initconst = { [UVIO_IOCTL_ADD_SECRET_NR] = BIT_UVC_CMD_ADD_SECRET, [UVIO_IOCTL_LIST_SECRETS_NR] = BIT_UVC_CMD_LIST_SECRETS, [UVIO_IOCTL_LOCK_SECRETS_NR] = BIT_UVC_CMD_LOCK_SECRETS, + [UVIO_IOCTL_RETR_SECRET_NR] = BIT_UVC_CMD_RETR_ATTEST, }; static_assert(ARRAY_SIZE(ioctl_nr_to_uvc_bit) == UVIO_IOCTL_NUM_IOCTLS); @@ -62,11 +63,13 @@ static void __init set_supp_uv_cmds(unsigned long *supp_uv_cmds) } /** - * uvio_uvdev_info() - get information about the uvdevice + * uvio_uvdev_info() - Get information about the uvdevice * * @uv_ioctl: ioctl control block * * Lists all IOCTLs that are supported by this uvdevice + * + * Return: 0 on success or a negative error code on error */ static int uvio_uvdev_info(struct uvio_ioctl_cb *uv_ioctl) { @@ -177,7 +180,7 @@ static int get_uvio_attest(struct uvio_ioctl_cb *uv_ioctl, struct uvio_attest *u * * Context: might sleep * - * Return: 0 on success or a negative error code on error. + * Return: 0 on success or a negative error code on error */ static int uvio_attestation(struct uvio_ioctl_cb *uv_ioctl) { @@ -237,7 +240,8 @@ out: return ret; } -/** uvio_add_secret() - perform an Add Secret UVC +/** + * uvio_add_secret() - Perform an Add Secret UVC * * @uv_ioctl: ioctl control block * @@ -260,7 +264,7 @@ out: * * Context: might sleep * - * Return: 0 on success or a negative error code on error. + * Return: 0 on success or a negative error code on error */ static int uvio_add_secret(struct uvio_ioctl_cb *uv_ioctl) { @@ -296,7 +300,44 @@ out: return ret; } -/** uvio_list_secrets() - perform a List Secret UVC +/* + * Do the actual secret list creation. Calls the list secrets UVC until there + * is no more space in the user buffer, or the list ends. + */ +static int uvio_get_list(void *zpage, struct uvio_ioctl_cb *uv_ioctl) +{ + const size_t data_off = offsetof(struct uv_secret_list, secrets); + u8 __user *user_buf = (u8 __user *)uv_ioctl->argument_addr; + struct uv_secret_list *list = zpage; + u16 num_secrets_stored = 0; + size_t user_off = data_off; + size_t copy_len; + + do { + uv_list_secrets(list, list->next_secret_idx, &uv_ioctl->uv_rc, + &uv_ioctl->uv_rrc); + if (uv_ioctl->uv_rc != UVC_RC_EXECUTED && + uv_ioctl->uv_rc != UVC_RC_MORE_DATA) + break; + + copy_len = sizeof(list->secrets[0]) * list->num_secr_stored; + if (copy_to_user(user_buf + user_off, list->secrets, copy_len)) + return -EFAULT; + + user_off += copy_len; + num_secrets_stored += list->num_secr_stored; + } while (uv_ioctl->uv_rc == UVC_RC_MORE_DATA && + user_off + sizeof(*list) <= uv_ioctl->argument_len); + + list->num_secr_stored = num_secrets_stored; + if (copy_to_user(user_buf, list, data_off)) + return -EFAULT; + return 0; +} + +/** + * uvio_list_secrets() - Perform a List Secret UVC + * * @uv_ioctl: ioctl control block * * uvio_list_secrets() performs the List Secret Ultravisor Call. It verifies @@ -307,45 +348,43 @@ out: * * The argument specifies the location for the result of the UV-Call. * + * Argument length must be a multiple of a page. + * The list secrets IOCTL will call the list UVC multiple times and fill + * the provided user-buffer with list elements until either the list ends or + * the buffer is full. The list header is merged over all list header from the + * individual UVCs. + * * If the List Secrets UV facility is not present, UV will return invalid * command rc. This won't be fenced in the driver and does not result in a * negative return value. * * Context: might sleep * - * Return: 0 on success or a negative error code on error. + * Return: 0 on success or a negative error code on error */ static int uvio_list_secrets(struct uvio_ioctl_cb *uv_ioctl) { - void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr; - struct uv_cb_guest_addr uvcb = { - .header.len = sizeof(uvcb), - .header.cmd = UVC_CMD_LIST_SECRETS, - }; - void *secrets = NULL; - int ret = 0; + void *zpage; + int rc; - if (uv_ioctl->argument_len != UVIO_LIST_SECRETS_LEN) + if (uv_ioctl->argument_len == 0 || + uv_ioctl->argument_len % UVIO_LIST_SECRETS_LEN != 0) return -EINVAL; - secrets = kvzalloc(UVIO_LIST_SECRETS_LEN, GFP_KERNEL); - if (!secrets) + zpage = (void *)get_zeroed_page(GFP_KERNEL); + if (!zpage) return -ENOMEM; - uvcb.addr = (u64)secrets; - uv_call_sched(0, (u64)&uvcb); - uv_ioctl->uv_rc = uvcb.header.rc; - uv_ioctl->uv_rrc = uvcb.header.rrc; - - if (copy_to_user(user_buf_arg, secrets, UVIO_LIST_SECRETS_LEN)) - ret = -EFAULT; + rc = uvio_get_list(zpage, uv_ioctl); - kvfree(secrets); - return ret; + free_page((unsigned long)zpage); + return rc; } -/** uvio_lock_secrets() - perform a Lock Secret Store UVC - * @uv_ioctl: ioctl control block +/** + * uvio_lock_secrets() - Perform a Lock Secret Store UVC + * + * @ioctl: ioctl control block * * uvio_lock_secrets() performs the Lock Secret Store Ultravisor Call. It * performs the UV-call and copies the return codes to the ioctl control block. @@ -360,7 +399,7 @@ static int uvio_list_secrets(struct uvio_ioctl_cb *uv_ioctl) * * Context: might sleep * - * Return: 0 on success or a negative error code on error. + * Return: 0 on success or a negative error code on error */ static int uvio_lock_secrets(struct uvio_ioctl_cb *ioctl) { @@ -379,6 +418,59 @@ static int uvio_lock_secrets(struct uvio_ioctl_cb *ioctl) return 0; } +/** + * uvio_retr_secret() - Perform a retrieve secret UVC + * + * @uv_ioctl: ioctl control block. + * + * uvio_retr_secret() performs the Retrieve Secret Ultravisor Call. + * The first two bytes of the argument specify the index of the secret to be + * retrieved. The retrieved secret is copied into the argument buffer if there + * is enough space. + * The argument length must be at least two bytes and at max 8192 bytes. + * + * Context: might sleep + * + * Return: 0 on success or a negative error code on error + */ +static int uvio_retr_secret(struct uvio_ioctl_cb *uv_ioctl) +{ + u16 __user *user_index = (u16 __user *)uv_ioctl->argument_addr; + struct uv_cb_retr_secr uvcb = { + .header.len = sizeof(uvcb), + .header.cmd = UVC_CMD_RETR_SECRET, + }; + u32 buf_len = uv_ioctl->argument_len; + void *buf = NULL; + int ret; + + if (buf_len > UVIO_RETR_SECRET_MAX_LEN || buf_len < sizeof(*user_index)) + return -EINVAL; + + buf = kvzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = -EFAULT; + if (get_user(uvcb.secret_idx, user_index)) + goto err; + + uvcb.buf_addr = (u64)buf; + uvcb.buf_size = buf_len; + uv_call_sched(0, (u64)&uvcb); + + if (copy_to_user((__user void *)uv_ioctl->argument_addr, buf, buf_len)) + goto err; + + ret = 0; + uv_ioctl->uv_rc = uvcb.header.rc; + uv_ioctl->uv_rrc = uvcb.header.rrc; + +err: + kvfree_sensitive(buf, buf_len); + return ret; +} + static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp, unsigned long cmd) { @@ -432,6 +524,9 @@ static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case UVIO_IOCTL_LOCK_SECRETS_NR: ret = uvio_lock_secrets(&uv_ioctl); break; + case UVIO_IOCTL_RETR_SECRET_NR: + ret = uvio_retr_secret(&uv_ioctl); + break; default: ret = -ENOIOCTLCMD; break; @@ -448,7 +543,6 @@ static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) static const struct file_operations uvio_dev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = uvio_ioctl, - .llseek = no_llseek, }; static struct miscdevice uvio_dev_miscdev = { diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index eb0520a9d4af..3a695c5bf77f 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -23,6 +23,7 @@ #include <linux/mutex.h> #include <linux/cma.h> #include <linux/mm.h> +#include <asm/machine.h> #include <asm/cpcmd.h> #include <asm/debug.h> #include <asm/vmcp.h> @@ -52,7 +53,7 @@ early_param("vmcp_cma", early_parse_vmcp_cma); void __init vmcp_cma_reserve(void) { - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return; cma_declare_contiguous(0, vmcp_cma_size, 0, 0, 0, false, "vmcp", &vmcp_cma); } @@ -242,7 +243,6 @@ static const struct file_operations vmcp_fops = { .write = vmcp_write, .unlocked_ioctl = vmcp_ioctl, .compat_ioctl = vmcp_ioctl, - .llseek = no_llseek, }; static struct miscdevice vmcp_dev = { @@ -255,7 +255,7 @@ static int __init vmcp_init(void) { int ret; - if (!MACHINE_IS_VM) + if (!machine_is_vm()) return 0; vmcp_debug = debug_register("vmcp", 1, 1, 240); diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index d7e408c8d0b8..e284eea331d7 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -23,6 +23,7 @@ #include <linux/spinlock.h> #include <linux/atomic.h> #include <linux/uaccess.h> +#include <asm/machine.h> #include <asm/cpcmd.h> #include <asm/debug.h> #include <asm/ebcdic.h> @@ -96,7 +97,6 @@ static const struct file_operations vmlogrdr_fops = { .open = vmlogrdr_open, .release = vmlogrdr_release, .read = vmlogrdr_read, - .llseek = no_llseek, }; @@ -124,7 +124,7 @@ static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue); */ static struct vmlogrdr_priv_t sys_ser[] = { - { .system_service = "*LOGREC ", + { .system_service = { '*', 'L', 'O', 'G', 'R', 'E', 'C', ' ' }, .internal_name = "logrec", .recording_name = "EREP", .minor_num = 0, @@ -133,7 +133,7 @@ static struct vmlogrdr_priv_t sys_ser[] = { .autorecording = 1, .autopurge = 1, }, - { .system_service = "*ACCOUNT", + { .system_service = { '*', 'A', 'C', 'C', 'O', 'U', 'N', 'T' }, .internal_name = "account", .recording_name = "ACCOUNT", .minor_num = 1, @@ -142,7 +142,7 @@ static struct vmlogrdr_priv_t sys_ser[] = { .autorecording = 1, .autopurge = 1, }, - { .system_service = "*SYMPTOM", + { .system_service = { '*', 'S', 'Y', 'M', 'P', 'T', 'O', 'M' }, .internal_name = "symptom", .recording_name = "SYMPTOM", .minor_num = 2, @@ -255,7 +255,7 @@ static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, /* * The recording commands needs to be called with option QID - * for guests that have previlege classes A or B. + * for guests that have privilege classes A or B. * Purging has to be done as separate step, because recording * can't be switched on as long as records are on the queue. * Doing both at the same time doesn't work. @@ -357,7 +357,7 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp) if (connect_rc) { pr_err("vmlogrdr: iucv connection to %s " "failed with rc %i \n", - logptr->system_service, connect_rc); + logptr->internal_name, connect_rc); goto out_path; } @@ -532,7 +532,7 @@ static ssize_t vmlogrdr_autopurge_show(struct device *dev, char *buf) { struct vmlogrdr_priv_t *priv = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", priv->autopurge); + return sysfs_emit(buf, "%u\n", priv->autopurge); } @@ -557,7 +557,7 @@ static ssize_t vmlogrdr_purge_store(struct device * dev, /* * The recording command needs to be called with option QID - * for guests that have previlege classes A or B. + * for guests that have privilege classes A or B. * Other guests will not recognize the command and we have to * issue the same command without the QID parameter. */ @@ -606,7 +606,7 @@ static ssize_t vmlogrdr_autorecording_show(struct device *dev, char *buf) { struct vmlogrdr_priv_t *priv = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", priv->autorecording); + return sysfs_emit(buf, "%u\n", priv->autorecording); } @@ -728,23 +728,9 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) struct device *dev; int ret; - dev = kzalloc(sizeof(struct device), GFP_KERNEL); - if (dev) { - dev_set_name(dev, "%s", priv->internal_name); - dev->bus = &iucv_bus; - dev->parent = iucv_root; - dev->driver = &vmlogrdr_driver; - dev->groups = vmlogrdr_attr_groups; - dev_set_drvdata(dev, priv); - /* - * The release function could be called after the - * module has been unloaded. It's _only_ task is to - * free the struct. Therefore, we specify kfree() - * directly here. (Probably a little bit obfuscating - * but legitime ...). - */ - dev->release = (void (*)(struct device *))kfree; - } else + dev = iucv_alloc_device(vmlogrdr_attr_groups, &vmlogrdr_driver, + priv, priv->internal_name); + if (!dev) return -ENOMEM; ret = device_register(dev); if (ret) { @@ -824,7 +810,7 @@ static int __init vmlogrdr_init(void) int i; dev_t dev; - if (! MACHINE_IS_VM) { + if (!machine_is_vm()) { pr_err("not running under VM, driver not loaded.\n"); return -ENODEV; } diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index fe94dec427b6..0fd918769a4b 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -18,6 +18,7 @@ #include <linux/kobject.h> #include <linux/uaccess.h> +#include <asm/machine.h> #include <asm/cio.h> #include <asm/ccwdev.h> #include <asm/debug.h> @@ -345,7 +346,7 @@ static ssize_t ur_attr_reclen_show(struct device *dev, urd = urdev_get_from_cdev(to_ccwdev(dev)); if (!urd) return -ENODEV; - rc = sprintf(buf, "%zu\n", urd->reclen); + rc = sysfs_emit(buf, "%zu\n", urd->reclen); urdev_put(urd); return rc; } @@ -1009,7 +1010,7 @@ static int __init ur_init(void) int rc; dev_t dev; - if (!MACHINE_IS_VM) { + if (!machine_is_vm()) { pr_err("The %s cannot be loaded without z/VM\n", ur_banner); return -ENODEV; diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 0969fa01df58..33cebb91b933 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -165,7 +165,6 @@ static const struct file_operations zcore_reipl_fops = { .write = zcore_reipl_write, .open = zcore_reipl_open, .release = zcore_reipl_release, - .llseek = no_llseek, }; static ssize_t zcore_hsa_read(struct file *filp, char __user *buf, @@ -200,7 +199,6 @@ static const struct file_operations zcore_hsa_fops = { .write = zcore_hsa_write, .read = zcore_hsa_read, .open = nonseekable_open, - .llseek = no_llseek, }; static int __init check_sdias(void) |