diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-04 22:17:38 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-04 22:17:38 +0300 |
commit | 2bb919b62f6e5959552a90a399d09d683afa3d1d (patch) | |
tree | 21e237db2bd0563dd458250d1b27d63a478bbcbe /drivers | |
parent | 0d4d4c6ff6debde4c44a418c59b304d4b514541c (diff) | |
parent | d4a01902eb59e478ab7c7d36d7bb90d94a315f89 (diff) | |
download | linux-2bb919b62f6e5959552a90a399d09d683afa3d1d.tar.xz |
Merge tag 's390-5.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Vasily Gorbik:
- Rework inline asm to get rid of error prone "register asm"
constructs, which are problematic especially when code
instrumentation is enabled.
In particular introduce and use register pair union to allocate
even/odd register pairs. Unfortunately this breaks compatibility with
older clang compilers and minimum clang version for s390 has been
raised to 13.
https://lore.kernel.org/linux-next/CAK7LNARuSmPCEy-ak0erPrPTgZdGVypBROFhtw+=3spoGoYsyw@mail.gmail.com/
- Fix gcc 11 warnings, which triggered various minor reworks all over
the code.
- Add zstd kernel image compression support.
- Rework boot CPU lowcore handling.
- De-duplicate and move kernel memory layout setup logic earlier.
- Few fixes in preparation for FORTIFY_SOURCE performing compile-time
and run-time field bounds checking for mem functions.
- Remove broken and unused power management support leftovers in s390
drivers.
- Disable stack-protector for decompressor and purgatory to fix
buildroot build.
- Fix vt220 sclp console name to match the char device name.
- Enable HAVE_IOREMAP_PROT and add zpci_set_irq()/zpci_clear_irq() in
zPCI code.
- Remove some implausible WARN_ON_ONCEs and remove arch specific
counter transaction call backs in favour of default transaction
handling in perf code.
- Extend/add new uevents for online/config/mode state changes of AP
card / queue device in zcrypt.
- Minor entry and ccwgroup code improvements.
- Other small various fixes and improvements all over the code.
* tag 's390-5.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (91 commits)
s390/dasd: use register pair instead of register asm
s390/qdio: get rid of register asm
s390/ioasm: use symbolic names for asm operands
s390/ioasm: get rid of register asm
s390/cmf: get rid of register asm
s390/lib,string: get rid of register asm
s390/lib,uaccess: get rid of register asm
s390/string: get rid of register asm
s390/cmpxchg: use register pair instead of register asm
s390/mm,pages-states: get rid of register asm
s390/lib,xor: get rid of register asm
s390/timex: get rid of register asm
s390/hypfs: use register pair instead of register asm
s390/zcrypt: Switch to flexible array member
s390/speculation: Use statically initialized const for instructions
virtio/s390: get rid of open-coded kvm hypercall
s390/pci: add zpci_set_irq()/zpci_clear_irq()
scripts/min-tool-version.sh: Raise minimum clang version to 13.0.0 for s390
s390/ipl: use register pair instead of register asm
s390/mem_detect: fix tprot() program check new psw handling
...
Diffstat (limited to 'drivers')
41 files changed, 327 insertions, 1076 deletions
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index fd42a5fffaed..6bb775236c16 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -69,25 +69,24 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */ * resulting condition code and DIAG return code. */ static inline int __dia250(void *iob, int cmd) { - register unsigned long reg2 asm ("2") = (unsigned long) iob; + union register_pair rx = { .even = (unsigned long)iob, }; typedef union { struct dasd_diag_init_io init_io; struct dasd_diag_rw_io rw_io; } addr_type; - int rc; + int cc; - rc = 3; + cc = 3; asm volatile( - " diag 2,%2,0x250\n" - "0: ipm %0\n" - " srl %0,28\n" - " or %0,3\n" + " diag %[rx],%[cmd],0x250\n" + "0: ipm %[cc]\n" + " srl %[cc],28\n" "1:\n" EX_TABLE(0b,1b) - : "+d" (rc), "=m" (*(addr_type *) iob) - : "d" (cmd), "d" (reg2), "m" (*(addr_type *) iob) - : "3", "cc"); - return rc; + : [cc] "+&d" (cc), [rx] "+&d" (rx.pair), "+m" (*(addr_type *)iob) + : [cmd] "d" (cmd) + : "cc"); + return cc | rx.odd; } static inline int dia250(void *iob, int cmd) diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 7faa56399999..29180bdf0977 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -17,7 +17,6 @@ #include <linux/blkdev.h> #include <linux/completion.h> #include <linux/interrupt.h> -#include <linux/platform_device.h> #include <linux/pfn_t.h> #include <linux/uio.h> #include <linux/dax.h> @@ -984,94 +983,11 @@ dcssblk_check_params(void) } /* - * Suspend / Resume - */ -static int dcssblk_freeze(struct device *dev) -{ - struct dcssblk_dev_info *dev_info; - int rc = 0; - - list_for_each_entry(dev_info, &dcssblk_devices, lh) { - switch (dev_info->segment_type) { - case SEG_TYPE_SR: - case SEG_TYPE_ER: - case SEG_TYPE_SC: - if (!dev_info->is_shared) - rc = -EINVAL; - break; - default: - rc = -EINVAL; - break; - } - if (rc) - break; - } - if (rc) - pr_err("Suspending the system failed because DCSS device %s " - "is writable\n", - dev_info->segment_name); - return rc; -} - -static int dcssblk_restore(struct device *dev) -{ - struct dcssblk_dev_info *dev_info; - struct segment_info *entry; - unsigned long start, end; - int rc = 0; - - list_for_each_entry(dev_info, &dcssblk_devices, lh) { - list_for_each_entry(entry, &dev_info->seg_list, lh) { - segment_unload(entry->segment_name); - rc = segment_load(entry->segment_name, SEGMENT_SHARED, - &start, &end); - if (rc < 0) { -// TODO in_use check ? - segment_warning(rc, entry->segment_name); - goto out_panic; - } - if (start != entry->start || end != entry->end) { - pr_err("The address range of DCSS %s changed " - "while the system was suspended\n", - entry->segment_name); - goto out_panic; - } - } - } - return 0; -out_panic: - panic("fatal dcssblk resume error\n"); -} - -static int dcssblk_thaw(struct device *dev) -{ - return 0; -} - -static const struct dev_pm_ops dcssblk_pm_ops = { - .freeze = dcssblk_freeze, - .thaw = dcssblk_thaw, - .restore = dcssblk_restore, -}; - -static struct platform_driver dcssblk_pdrv = { - .driver = { - .name = "dcssblk", - .pm = &dcssblk_pm_ops, - }, -}; - -static struct platform_device *dcssblk_pdev; - - -/* * The init/exit functions. */ static void __exit dcssblk_exit(void) { - platform_device_unregister(dcssblk_pdev); - platform_driver_unregister(&dcssblk_pdrv); root_device_unregister(dcssblk_root_dev); unregister_blkdev(dcssblk_major, DCSSBLK_NAME); } @@ -1081,22 +997,9 @@ dcssblk_init(void) { int rc; - rc = platform_driver_register(&dcssblk_pdrv); - if (rc) - return rc; - - dcssblk_pdev = platform_device_register_simple("dcssblk", -1, NULL, - 0); - if (IS_ERR(dcssblk_pdev)) { - rc = PTR_ERR(dcssblk_pdev); - goto out_pdrv; - } - dcssblk_root_dev = root_device_register("dcssblk"); - if (IS_ERR(dcssblk_root_dev)) { - rc = PTR_ERR(dcssblk_root_dev); - goto out_pdev; - } + if (IS_ERR(dcssblk_root_dev)) + return PTR_ERR(dcssblk_root_dev); rc = device_create_file(dcssblk_root_dev, &dev_attr_add); if (rc) goto out_root; @@ -1114,10 +1017,7 @@ dcssblk_init(void) out_root: root_device_unregister(dcssblk_root_dev); -out_pdev: - platform_device_unregister(dcssblk_pdev); -out_pdrv: - platform_driver_unregister(&dcssblk_pdrv); + return rc; } diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 91ef710edfd2..ce98fab4d43c 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -39,8 +39,6 @@ #include <linux/hdreg.h> /* HDIO_GETGEO */ #include <linux/device.h> #include <linux/bio.h> -#include <linux/suspend.h> -#include <linux/platform_device.h> #include <linux/gfp.h> #include <linux/uaccess.h> @@ -140,7 +138,7 @@ static long xpram_page_out (unsigned long page_addr, unsigned int xpage_index) /* * Check if xpram is available. */ -static int xpram_present(void) +static int __init xpram_present(void) { unsigned long mem_page; int rc; @@ -156,7 +154,7 @@ static int xpram_present(void) /* * Return index of the last available xpram page. */ -static unsigned long xpram_highest_page_index(void) +static unsigned long __init xpram_highest_page_index(void) { unsigned int page_index, add_bit; unsigned long mem_page; @@ -384,42 +382,6 @@ out: } /* - * Resume failed: Print error message and call panic. - */ -static void xpram_resume_error(const char *message) -{ - pr_err("Resuming the system failed: %s\n", message); - panic("xpram resume error\n"); -} - -/* - * Check if xpram setup changed between suspend and resume. - */ -static int xpram_restore(struct device *dev) -{ - if (!xpram_pages) - return 0; - if (xpram_present() != 0) - xpram_resume_error("xpram disappeared"); - if (xpram_pages != xpram_highest_page_index() + 1) - xpram_resume_error("Size of xpram changed"); - return 0; -} - -static const struct dev_pm_ops xpram_pm_ops = { - .restore = xpram_restore, -}; - -static struct platform_driver xpram_pdrv = { - .driver = { - .name = XPRAM_NAME, - .pm = &xpram_pm_ops, - }, -}; - -static struct platform_device *xpram_pdev; - -/* * Finally, the init/exit functions. */ static void __exit xpram_exit(void) @@ -430,8 +392,6 @@ static void __exit xpram_exit(void) blk_cleanup_disk(xpram_disks[i]); } unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); - platform_device_unregister(xpram_pdev); - platform_driver_unregister(&xpram_pdrv); } static int __init xpram_init(void) @@ -449,24 +409,7 @@ static int __init xpram_init(void) rc = xpram_setup_sizes(xpram_pages); if (rc) return rc; - rc = platform_driver_register(&xpram_pdrv); - if (rc) - return rc; - xpram_pdev = platform_device_register_simple(XPRAM_NAME, -1, NULL, 0); - if (IS_ERR(xpram_pdev)) { - rc = PTR_ERR(xpram_pdev); - goto fail_platform_driver_unregister; - } - rc = xpram_setup_blkdev(); - if (rc) - goto fail_platform_device_unregister; - return 0; - -fail_platform_device_unregister: - platform_device_unregister(xpram_pdev); -fail_platform_driver_unregister: - platform_driver_unregister(&xpram_pdrv); - return rc; + return xpram_setup_blkdev(); } module_init(xpram_init); diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 7bc616b253f1..9fa92e45e0ee 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c @@ -21,7 +21,6 @@ #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/poll.h> -#include <linux/device.h> #include <linux/slab.h> #include <net/iucv/iucv.h> #include <linux/uaccess.h> @@ -79,8 +78,6 @@ static u8 user_data_sever[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; -static struct device *monreader_device; - /****************************************************************************** * helper functions * *****************************************************************************/ @@ -319,7 +316,6 @@ static int mon_open(struct inode *inode, struct file *filp) goto out_path; } filp->private_data = monpriv; - dev_set_drvdata(monreader_device, monpriv); return nonseekable_open(inode, filp); out_path: @@ -354,7 +350,6 @@ static int mon_close(struct inode *inode, struct file *filp) atomic_set(&monpriv->msglim_count, 0); monpriv->write_index = 0; monpriv->read_index = 0; - dev_set_drvdata(monreader_device, NULL); for (i = 0; i < MON_MSGLIM; i++) kfree(monpriv->msg_array[i]); @@ -456,94 +451,6 @@ static struct miscdevice mon_dev = { .minor = MISC_DYNAMIC_MINOR, }; - -/****************************************************************************** - * suspend / resume * - *****************************************************************************/ -static int monreader_freeze(struct device *dev) -{ - struct mon_private *monpriv = dev_get_drvdata(dev); - int rc; - - if (!monpriv) - return 0; - if (monpriv->path) { - rc = iucv_path_sever(monpriv->path, user_data_sever); - if (rc) - pr_warn("Disconnecting the z/VM *MONITOR system service failed with rc=%i\n", - rc); - iucv_path_free(monpriv->path); - } - atomic_set(&monpriv->iucv_severed, 0); - atomic_set(&monpriv->iucv_connected, 0); - atomic_set(&monpriv->read_ready, 0); - atomic_set(&monpriv->msglim_count, 0); - monpriv->write_index = 0; - monpriv->read_index = 0; - monpriv->path = NULL; - return 0; -} - -static int monreader_thaw(struct device *dev) -{ - struct mon_private *monpriv = dev_get_drvdata(dev); - int rc; - - if (!monpriv) - return 0; - rc = -ENOMEM; - monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL); - if (!monpriv->path) - goto out; - rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler, - MON_SERVICE, NULL, user_data_connect, monpriv); - if (rc) { - pr_err("Connecting to the z/VM *MONITOR system service " - "failed with rc=%i\n", rc); - goto out_path; - } - wait_event(mon_conn_wait_queue, - atomic_read(&monpriv->iucv_connected) || - atomic_read(&monpriv->iucv_severed)); - if (atomic_read(&monpriv->iucv_severed)) - goto out_path; - return 0; -out_path: - rc = -EIO; - iucv_path_free(monpriv->path); - monpriv->path = NULL; -out: - atomic_set(&monpriv->iucv_severed, 1); - return rc; -} - -static int monreader_restore(struct device *dev) -{ - int rc; - - segment_unload(mon_dcss_name); - rc = segment_load(mon_dcss_name, SEGMENT_SHARED, - &mon_dcss_start, &mon_dcss_end); - if (rc < 0) { - segment_warning(rc, mon_dcss_name); - panic("fatal monreader resume error: no monitor dcss\n"); - } - return monreader_thaw(dev); -} - -static const struct dev_pm_ops monreader_pm_ops = { - .freeze = monreader_freeze, - .thaw = monreader_thaw, - .restore = monreader_restore, -}; - -static struct device_driver monreader_driver = { - .name = "monreader", - .bus = &iucv_bus, - .pm = &monreader_pm_ops, -}; - - /****************************************************************************** * module init/exit * *****************************************************************************/ @@ -567,36 +474,16 @@ static int __init mon_init(void) return rc; } - rc = driver_register(&monreader_driver); - if (rc) - goto out_iucv; - monreader_device = kzalloc(sizeof(struct device), GFP_KERNEL); - if (!monreader_device) { - rc = -ENOMEM; - goto out_driver; - } - - dev_set_name(monreader_device, "monreader-dev"); - monreader_device->bus = &iucv_bus; - monreader_device->parent = iucv_root; - monreader_device->driver = &monreader_driver; - monreader_device->release = (void (*)(struct device *))kfree; - rc = device_register(monreader_device); - if (rc) { - put_device(monreader_device); - goto out_driver; - } - rc = segment_type(mon_dcss_name); if (rc < 0) { segment_warning(rc, mon_dcss_name); - goto out_device; + goto out_iucv; } if (rc != SEG_TYPE_SC) { pr_err("The specified *MONITOR DCSS %s does not have the " "required type SC\n", mon_dcss_name); rc = -EINVAL; - goto out_device; + goto out_iucv; } rc = segment_load(mon_dcss_name, SEGMENT_SHARED, @@ -604,7 +491,7 @@ static int __init mon_init(void) if (rc < 0) { segment_warning(rc, mon_dcss_name); rc = -EINVAL; - goto out_device; + goto out_iucv; } dcss_mkname(mon_dcss_name, &user_data_connect[8]); @@ -619,10 +506,6 @@ static int __init mon_init(void) out: segment_unload(mon_dcss_name); -out_device: - device_unregister(monreader_device); -out_driver: - driver_unregister(&monreader_driver); out_iucv: iucv_unregister(&monreader_iucv_handler, 1); return rc; @@ -632,8 +515,6 @@ static void __exit mon_exit(void) { segment_unload(mon_dcss_name); misc_deregister(&mon_dev); - device_unregister(monreader_device); - driver_unregister(&monreader_driver); iucv_unregister(&monreader_iucv_handler, 1); return; } diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index fdc0c0b7a6f5..9cd1ea92d619 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c @@ -20,7 +20,6 @@ #include <linux/ctype.h> #include <linux/poll.h> #include <linux/mutex.h> -#include <linux/platform_device.h> #include <linux/slab.h> #include <linux/uaccess.h> #include <asm/ebcdic.h> @@ -40,10 +39,7 @@ struct mon_buf { char *data; }; -static LIST_HEAD(mon_priv_list); - struct mon_private { - struct list_head priv_list; struct list_head list; struct monwrite_hdr hdr; size_t hdr_to_read; @@ -199,7 +195,6 @@ static int monwrite_open(struct inode *inode, struct file *filp) monpriv->hdr_to_read = sizeof(monpriv->hdr); mutex_init(&monpriv->thread_mutex); filp->private_data = monpriv; - list_add_tail(&monpriv->priv_list, &mon_priv_list); return nonseekable_open(inode, filp); } @@ -217,7 +212,6 @@ static int monwrite_close(struct inode *inode, struct file *filp) kfree(entry->data); kfree(entry); } - list_del(&monpriv->priv_list); kfree(monpriv); return 0; } @@ -294,105 +288,23 @@ static struct miscdevice mon_dev = { }; /* - * suspend/resume - */ - -static int monwriter_freeze(struct device *dev) -{ - struct mon_private *monpriv; - struct mon_buf *monbuf; - - list_for_each_entry(monpriv, &mon_priv_list, priv_list) { - list_for_each_entry(monbuf, &monpriv->list, list) { - if (monbuf->hdr.mon_function != MONWRITE_GEN_EVENT) - monwrite_diag(&monbuf->hdr, monbuf->data, - APPLDATA_STOP_REC); - } - } - return 0; -} - -static int monwriter_restore(struct device *dev) -{ - struct mon_private *monpriv; - struct mon_buf *monbuf; - - list_for_each_entry(monpriv, &mon_priv_list, priv_list) { - list_for_each_entry(monbuf, &monpriv->list, list) { - if (monbuf->hdr.mon_function == MONWRITE_START_INTERVAL) - monwrite_diag(&monbuf->hdr, monbuf->data, - APPLDATA_START_INTERVAL_REC); - if (monbuf->hdr.mon_function == MONWRITE_START_CONFIG) - monwrite_diag(&monbuf->hdr, monbuf->data, - APPLDATA_START_CONFIG_REC); - } - } - return 0; -} - -static int monwriter_thaw(struct device *dev) -{ - return monwriter_restore(dev); -} - -static const struct dev_pm_ops monwriter_pm_ops = { - .freeze = monwriter_freeze, - .thaw = monwriter_thaw, - .restore = monwriter_restore, -}; - -static struct platform_driver monwriter_pdrv = { - .driver = { - .name = "monwriter", - .pm = &monwriter_pm_ops, - }, -}; - -static struct platform_device *monwriter_pdev; - -/* * module init/exit */ static int __init mon_init(void) { - int rc; - if (!MACHINE_IS_VM) return -ENODEV; - - rc = platform_driver_register(&monwriter_pdrv); - if (rc) - return rc; - - monwriter_pdev = platform_device_register_simple("monwriter", -1, NULL, - 0); - if (IS_ERR(monwriter_pdev)) { - rc = PTR_ERR(monwriter_pdev); - goto out_driver; - } - /* * misc_register() has to be the last action in module_init(), because * file operations will be available right after this. */ - rc = misc_register(&mon_dev); - if (rc) - goto out_device; - return 0; - -out_device: - platform_device_unregister(monwriter_pdev); -out_driver: - platform_driver_unregister(&monwriter_pdrv); - return rc; + return misc_register(&mon_dev); } static void __exit mon_exit(void) { misc_deregister(&mon_dev); - platform_device_unregister(monwriter_pdev); - platform_driver_unregister(&monwriter_pdrv); } module_init(mon_init); diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 6627820a5eb9..792b4bfa6d9a 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -18,8 +18,6 @@ #include <linux/reboot.h> #include <linux/jiffies.h> #include <linux/init.h> -#include <linux/suspend.h> -#include <linux/completion.h> #include <linux/platform_device.h> #include <asm/types.h> #include <asm/irq.h> @@ -49,9 +47,6 @@ static struct sclp_req sclp_init_req; static void *sclp_read_sccb; static struct init_sccb *sclp_init_sccb; -/* Suspend request */ -static DECLARE_COMPLETION(sclp_request_queue_flushed); - /* Number of console pages to allocate, used by sclp_con.c and sclp_vt220.c */ int sclp_console_pages = SCLP_CONSOLE_PAGES; /* Flag to indicate if buffer pages are dropped on buffer full condition */ @@ -59,11 +54,6 @@ int sclp_console_drop = 1; /* Number of times the console dropped buffer pages */ unsigned long sclp_console_full; -static void sclp_suspend_req_cb(struct sclp_req *req, void *data) -{ - complete(&sclp_request_queue_flushed); -} - static int __init sclp_setup_console_pages(char *str) { int pages, rc; @@ -88,8 +78,6 @@ static int __init sclp_setup_console_drop(char *str) __setup("sclp_con_drop=", sclp_setup_console_drop); -static struct sclp_req sclp_suspend_req; - /* Timer for request retries. */ static struct timer_list sclp_request_timer; @@ -123,12 +111,6 @@ static volatile enum sclp_mask_state_t { sclp_mask_state_initializing } sclp_mask_state = sclp_mask_state_idle; -/* Internal state: is the driver suspended? */ -static enum sclp_suspend_state_t { - sclp_suspend_state_running, - sclp_suspend_state_suspended, -} sclp_suspend_state = sclp_suspend_state_running; - /* Maximum retry counts */ #define SCLP_INIT_RETRY 3 #define SCLP_MASK_RETRY 3 @@ -314,8 +296,6 @@ sclp_process_queue(void) del_timer(&sclp_request_timer); while (!list_empty(&sclp_req_queue)) { req = list_entry(sclp_req_queue.next, struct sclp_req, list); - if (!req->sccb) - goto do_post; rc = __sclp_start_request(req); if (rc == 0) break; @@ -327,7 +307,6 @@ sclp_process_queue(void) sclp_request_timeout_normal); break; } -do_post: /* Post-processing for aborted request */ list_del(&req->list); if (req->callback) { @@ -341,10 +320,8 @@ do_post: static int __sclp_can_add_request(struct sclp_req *req) { - if (req == &sclp_suspend_req || req == &sclp_init_req) + if (req == &sclp_init_req) return 1; - if (sclp_suspend_state != sclp_suspend_state_running) - return 0; if (sclp_init_state != sclp_init_state_initialized) return 0; if (sclp_activation_state != sclp_activation_state_active) @@ -378,16 +355,10 @@ sclp_add_request(struct sclp_req *req) /* Start if request is first in list */ if (sclp_running_state == sclp_running_state_idle && req->list.prev == &sclp_req_queue) { - if (!req->sccb) { - list_del(&req->list); - rc = -ENODATA; - goto out; - } rc = __sclp_start_request(req); if (rc) list_del(&req->list); } -out: spin_unlock_irqrestore(&sclp_lock, flags); return rc; } @@ -693,7 +664,6 @@ sclp_register(struct sclp_register *reg) /* Trigger initial state change callback */ reg->sclp_receive_mask = 0; reg->sclp_send_mask = 0; - reg->pm_event_posted = 0; list_add(®->list, &sclp_reg_list); spin_unlock_irqrestore(&sclp_lock, flags); rc = sclp_init_mask(1); @@ -1011,112 +981,6 @@ static struct notifier_block sclp_reboot_notifier = { .notifier_call = sclp_reboot_event }; -/* - * Suspend/resume SCLP notifier implementation - */ - -static void sclp_pm_event(enum sclp_pm_event sclp_pm_event, int rollback) -{ - struct sclp_register *reg; - unsigned long flags; - - if (!rollback) { - spin_lock_irqsave(&sclp_lock, flags); - list_for_each_entry(reg, &sclp_reg_list, list) - reg->pm_event_posted = 0; - spin_unlock_irqrestore(&sclp_lock, flags); - } - do { - spin_lock_irqsave(&sclp_lock, flags); - list_for_each_entry(reg, &sclp_reg_list, list) { - if (rollback && reg->pm_event_posted) - goto found; - if (!rollback && !reg->pm_event_posted) - goto found; - } - spin_unlock_irqrestore(&sclp_lock, flags); - return; -found: - spin_unlock_irqrestore(&sclp_lock, flags); - if (reg->pm_event_fn) - reg->pm_event_fn(reg, sclp_pm_event); - reg->pm_event_posted = rollback ? 0 : 1; - } while (1); -} - -/* - * Susend/resume callbacks for platform device - */ - -static int sclp_freeze(struct device *dev) -{ - unsigned long flags; - int rc; - - sclp_pm_event(SCLP_PM_EVENT_FREEZE, 0); - - spin_lock_irqsave(&sclp_lock, flags); - sclp_suspend_state = sclp_suspend_state_suspended; - spin_unlock_irqrestore(&sclp_lock, flags); - - /* Init supend data */ - memset(&sclp_suspend_req, 0, sizeof(sclp_suspend_req)); - sclp_suspend_req.callback = sclp_suspend_req_cb; - sclp_suspend_req.status = SCLP_REQ_FILLED; - init_completion(&sclp_request_queue_flushed); - - rc = sclp_add_request(&sclp_suspend_req); - if (rc == 0) - wait_for_completion(&sclp_request_queue_flushed); - else if (rc != -ENODATA) - goto fail_thaw; - - rc = sclp_deactivate(); - if (rc) - goto fail_thaw; - return 0; - -fail_thaw: - spin_lock_irqsave(&sclp_lock, flags); - sclp_suspend_state = sclp_suspend_state_running; - spin_unlock_irqrestore(&sclp_lock, flags); - sclp_pm_event(SCLP_PM_EVENT_THAW, 1); - return rc; -} - -static int sclp_undo_suspend(enum sclp_pm_event event) -{ - unsigned long flags; - int rc; - - rc = sclp_reactivate(); - if (rc) - return rc; - - spin_lock_irqsave(&sclp_lock, flags); - sclp_suspend_state = sclp_suspend_state_running; - spin_unlock_irqrestore(&sclp_lock, flags); - - sclp_pm_event(event, 0); - return 0; -} - -static int sclp_thaw(struct device *dev) -{ - return sclp_undo_suspend(SCLP_PM_EVENT_THAW); -} - -static int sclp_restore(struct device *dev) -{ - return sclp_undo_suspend(SCLP_PM_EVENT_RESTORE); -} - -static const struct dev_pm_ops sclp_pm_ops = { - .freeze = sclp_freeze, - .thaw = sclp_thaw, - .restore = sclp_restore, -}; - static ssize_t con_pages_show(struct device_driver *dev, char *buf) { return sprintf(buf, "%i\n", sclp_console_pages); @@ -1155,13 +1019,10 @@ static const struct attribute_group *sclp_drv_attr_groups[] = { static struct platform_driver sclp_pdrv = { .driver = { .name = "sclp", - .pm = &sclp_pm_ops, .groups = sclp_drv_attr_groups, }, }; -static struct platform_device *sclp_pdev; - /* Initialize SCLP driver. Return zero if driver is operational, non-zero * otherwise. */ static int @@ -1215,23 +1076,6 @@ fail_unlock: return rc; } -/* - * SCLP panic notifier: If we are suspended, we thaw SCLP in order to be able - * to print the panic message. - */ -static int sclp_panic_notify(struct notifier_block *self, - unsigned long event, void *data) -{ - if (sclp_suspend_state == sclp_suspend_state_suspended) - sclp_undo_suspend(SCLP_PM_EVENT_THAW); - return NOTIFY_OK; -} - -static struct notifier_block sclp_on_panic_nb = { - .notifier_call = sclp_panic_notify, - .priority = SCLP_PANIC_PRIO, -}; - static __init int sclp_initcall(void) { int rc; @@ -1240,23 +1084,7 @@ static __init int sclp_initcall(void) if (rc) return rc; - sclp_pdev = platform_device_register_simple("sclp", -1, NULL, 0); - rc = PTR_ERR_OR_ZERO(sclp_pdev); - if (rc) - goto fail_platform_driver_unregister; - - rc = atomic_notifier_chain_register(&panic_notifier_list, - &sclp_on_panic_nb); - if (rc) - goto fail_platform_device_unregister; - return sclp_init(); - -fail_platform_device_unregister: - platform_device_unregister(sclp_pdev); -fail_platform_driver_unregister: - platform_driver_unregister(&sclp_pdrv); - return rc; } arch_initcall(sclp_initcall); diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 6de919944a39..8dd8ad83b78b 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -81,15 +81,6 @@ typedef unsigned int sclp_cmdw_t; #define GDS_KEY_SELFDEFTEXTMSG 0x31 -enum sclp_pm_event { - SCLP_PM_EVENT_FREEZE, - SCLP_PM_EVENT_THAW, - SCLP_PM_EVENT_RESTORE, -}; - -#define SCLP_PANIC_PRIO 1 -#define SCLP_PANIC_PRIO_CLIENT 0 - typedef u64 sccb_mask_t; struct sccb_header { @@ -293,10 +284,6 @@ struct sclp_register { void (*state_change_fn)(struct sclp_register *); /* called for events in cp_receive_mask/sclp_receive_mask */ void (*receiver_fn)(struct evbuf_header *); - /* called for power management events */ - void (*pm_event_fn)(struct sclp_register *, enum sclp_pm_event); - /* pm event posted flag */ - int pm_event_posted; }; /* externals from sclp.c */ diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index d41bc144c183..ab0518cfdcfe 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -20,7 +20,6 @@ #include <linux/mmzone.h> #include <linux/memory.h> #include <linux/module.h> -#include <linux/platform_device.h> #include <asm/ctl_reg.h> #include <asm/chpid.h> #include <asm/setup.h> @@ -168,7 +167,6 @@ static DEFINE_MUTEX(sclp_mem_mutex); static LIST_HEAD(sclp_mem_list); static u8 sclp_max_storage_id; static DECLARE_BITMAP(sclp_storage_ids, 256); -static int sclp_mem_state_changed; struct memory_increment { struct list_head list; @@ -359,8 +357,6 @@ static int sclp_mem_notifier(struct notifier_block *nb, rc = -EINVAL; break; } - if (!rc) - sclp_mem_state_changed = 1; mutex_unlock(&sclp_mem_mutex); return rc ? NOTIFY_BAD : NOTIFY_OK; } @@ -456,28 +452,8 @@ static void __init insert_increment(u16 rn, int standby, int assigned) list_add(&new_incr->list, prev); } -static int sclp_mem_freeze(struct device *dev) -{ - if (!sclp_mem_state_changed) - return 0; - pr_err("Memory hotplug state changed, suspend refused.\n"); - return -EPERM; -} - -static const struct dev_pm_ops sclp_mem_pm_ops = { - .freeze = sclp_mem_freeze, -}; - -static struct platform_driver sclp_mem_pdrv = { - .driver = { - .name = "sclp_mem", - .pm = &sclp_mem_pm_ops, - }, -}; - static int __init sclp_detect_standby_memory(void) { - struct platform_device *sclp_pdev; struct read_storage_sccb *sccb; int i, id, assigned, rc; @@ -530,17 +506,7 @@ static int __init sclp_detect_standby_memory(void) rc = register_memory_notifier(&sclp_mem_nb); if (rc) goto out; - rc = platform_driver_register(&sclp_mem_pdrv); - if (rc) - goto out; - sclp_pdev = platform_device_register_simple("sclp_mem", -1, NULL, 0); - rc = PTR_ERR_OR_ZERO(sclp_pdev); - if (rc) - goto out_driver; sclp_add_standby_memory(); - goto out; -out_driver: - platform_driver_unregister(&sclp_mem_pdrv); out: free_page((unsigned long) sccb); return rc; diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index cc01a7b8595d..de028868c6f4 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c @@ -36,8 +36,6 @@ static LIST_HEAD(sclp_con_outqueue); static struct sclp_buffer *sclp_conbuf; /* Timer for delayed output of console messages */ static struct timer_list sclp_con_timer; -/* Suspend mode flag */ -static int sclp_con_suspended; /* Flag that output queue is currently running */ static int sclp_con_queue_running; @@ -64,7 +62,7 @@ sclp_conbuf_callback(struct sclp_buffer *buffer, int rc) if (!list_empty(&sclp_con_outqueue)) buffer = list_first_entry(&sclp_con_outqueue, struct sclp_buffer, list); - if (!buffer || sclp_con_suspended) { + if (!buffer) { sclp_con_queue_running = 0; spin_unlock_irqrestore(&sclp_con_lock, flags); break; @@ -86,7 +84,7 @@ static void sclp_conbuf_emit(void) if (sclp_conbuf) list_add_tail(&sclp_conbuf->list, &sclp_con_outqueue); sclp_conbuf = NULL; - if (sclp_con_queue_running || sclp_con_suspended) + if (sclp_con_queue_running) goto out_unlock; if (list_empty(&sclp_con_outqueue)) goto out_unlock; @@ -180,8 +178,6 @@ sclp_console_write(struct console *console, const char *message, if (list_empty(&sclp_con_pages)) sclp_console_full++; while (list_empty(&sclp_con_pages)) { - if (sclp_con_suspended) - goto out; if (sclp_console_drop_buffer()) break; spin_unlock_irqrestore(&sclp_con_lock, flags); @@ -214,7 +210,6 @@ sclp_console_write(struct console *console, const char *message, !timer_pending(&sclp_con_timer)) { mod_timer(&sclp_con_timer, jiffies + HZ / 10); } -out: spin_unlock_irqrestore(&sclp_con_lock, flags); } @@ -235,32 +230,6 @@ sclp_console_flush(void) sclp_console_sync_queue(); } -/* - * Resume console: If there are cached messages, emit them. - */ -static void sclp_console_resume(void) -{ - unsigned long flags; - - spin_lock_irqsave(&sclp_con_lock, flags); - sclp_con_suspended = 0; - spin_unlock_irqrestore(&sclp_con_lock, flags); - sclp_conbuf_emit(); -} - -/* - * Suspend console: Set suspend flag and flush console - */ -static void sclp_console_suspend(void) -{ - unsigned long flags; - - spin_lock_irqsave(&sclp_con_lock, flags); - sclp_con_suspended = 1; - spin_unlock_irqrestore(&sclp_con_lock, flags); - sclp_console_flush(); -} - static int sclp_console_notify(struct notifier_block *self, unsigned long event, void *data) { @@ -270,7 +239,7 @@ static int sclp_console_notify(struct notifier_block *self, static struct notifier_block on_panic_nb = { .notifier_call = sclp_console_notify, - .priority = SCLP_PANIC_PRIO_CLIENT, + .priority = 1, }; static struct notifier_block on_reboot_nb = { @@ -292,22 +261,6 @@ static struct console sclp_console = }; /* - * This function is called for SCLP suspend and resume events. - */ -void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event) -{ - switch (sclp_pm_event) { - case SCLP_PM_EVENT_FREEZE: - sclp_console_suspend(); - break; - case SCLP_PM_EVENT_RESTORE: - case SCLP_PM_EVENT_THAW: - sclp_console_resume(); - break; - } -} - -/* * called by console_init() in drivers/char/tty_io.c at boot-time. */ static int __init diff --git a/drivers/s390/char/sclp_ftp.c b/drivers/s390/char/sclp_ftp.c index dfdd6c8fd17e..1e9de99dcd02 100644 --- a/drivers/s390/char/sclp_ftp.c +++ b/drivers/s390/char/sclp_ftp.c @@ -231,7 +231,6 @@ static struct sclp_register sclp_ftp_event = { .receive_mask = EVTYP_DIAG_TEST_MASK, /* want rx events */ .receiver_fn = sclp_ftp_rxcb, /* async callback (rx) */ .state_change_fn = NULL, - .pm_event_fn = NULL, }; /** diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c index 76956c2131cd..ade721467804 100644 --- a/drivers/s390/char/sclp_quiesce.c +++ b/drivers/s390/char/sclp_quiesce.c @@ -18,10 +18,6 @@ #include "sclp.h" -static void (*old_machine_restart)(char *); -static void (*old_machine_halt)(void); -static void (*old_machine_power_off)(void); - /* Shutdown handler. Signal completion of shutdown by loading special PSW. */ static void do_machine_quiesce(void) { @@ -37,42 +33,15 @@ static void do_machine_quiesce(void) /* Handler for quiesce event. Start shutdown procedure. */ static void sclp_quiesce_handler(struct evbuf_header *evbuf) { - if (_machine_restart != (void *) do_machine_quiesce) { - old_machine_restart = _machine_restart; - old_machine_halt = _machine_halt; - old_machine_power_off = _machine_power_off; - _machine_restart = (void *) do_machine_quiesce; - _machine_halt = do_machine_quiesce; - _machine_power_off = do_machine_quiesce; - } + _machine_restart = (void *) do_machine_quiesce; + _machine_halt = do_machine_quiesce; + _machine_power_off = do_machine_quiesce; ctrl_alt_del(); } -/* Undo machine restart/halt/power_off modification on resume */ -static void sclp_quiesce_pm_event(struct sclp_register *reg, - enum sclp_pm_event sclp_pm_event) -{ - switch (sclp_pm_event) { - case SCLP_PM_EVENT_RESTORE: - if (old_machine_restart) { - _machine_restart = old_machine_restart; - _machine_halt = old_machine_halt; - _machine_power_off = old_machine_power_off; - old_machine_restart = NULL; - old_machine_halt = NULL; - old_machine_power_off = NULL; - } - break; - case SCLP_PM_EVENT_FREEZE: - case SCLP_PM_EVENT_THAW: - break; - } -} - static struct sclp_register sclp_quiesce_event = { .receive_mask = EVTYP_SIGQUIESCE_MASK, .receiver_fn = sclp_quiesce_handler, - .pm_event_fn = sclp_quiesce_pm_event }; /* Initialize quiesce driver. */ diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c index d6c84e354df5..de44c15fe03a 100644 --- a/drivers/s390/char/sclp_rw.c +++ b/drivers/s390/char/sclp_rw.c @@ -26,16 +26,9 @@ */ #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer)) -static void sclp_rw_pm_event(struct sclp_register *reg, - enum sclp_pm_event sclp_pm_event) -{ - sclp_console_pm_event(sclp_pm_event); -} - /* Event type structure for write message and write priority message */ static struct sclp_register sclp_rw_event = { .send_mask = EVTYP_MSG_MASK, - .pm_event_fn = sclp_rw_pm_event, }; /* diff --git a/drivers/s390/char/sclp_rw.h b/drivers/s390/char/sclp_rw.h index 93d706e4935c..a9127489f224 100644 --- a/drivers/s390/char/sclp_rw.h +++ b/drivers/s390/char/sclp_rw.h @@ -88,10 +88,4 @@ int sclp_write(struct sclp_buffer *buffer, const unsigned char *, int); int sclp_emit_buffer(struct sclp_buffer *,void (*)(struct sclp_buffer *,int)); int sclp_chars_in_buffer(struct sclp_buffer *); -#ifdef CONFIG_SCLP_CONSOLE -void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event); -#else -static inline void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event) { } -#endif - #endif /* __SCLP_RW_H__ */ diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 4456ceb23bd2..f5591bf82a8f 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -284,7 +284,6 @@ static int sclp_tty_chars_in_buffer(struct tty_struct *tty) { unsigned long flags; - struct list_head *l; struct sclp_buffer *t; int count; @@ -292,8 +291,7 @@ sclp_tty_chars_in_buffer(struct tty_struct *tty) count = 0; if (sclp_ttybuf != NULL) count = sclp_chars_in_buffer(sclp_ttybuf); - list_for_each(l, &sclp_tty_outqueue) { - t = list_entry(l, struct sclp_buffer, list); + list_for_each_entry(t, &sclp_tty_outqueue, list) { count += sclp_chars_in_buffer(t); } spin_unlock_irqrestore(&sclp_tty_lock, flags); diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 5b8a7b090a97..fa40057fd18d 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -36,8 +36,8 @@ #define SCLP_VT220_MINOR 65 #define SCLP_VT220_DRIVER_NAME "sclp_vt220" #define SCLP_VT220_DEVICE_NAME "ttysclp" -#define SCLP_VT220_CONSOLE_NAME "ttyS" -#define SCLP_VT220_CONSOLE_INDEX 1 /* console=ttyS1 */ +#define SCLP_VT220_CONSOLE_NAME "ttysclp" +#define SCLP_VT220_CONSOLE_INDEX 0 /* console=ttysclp0 */ /* Representation of a single write request */ struct sclp_vt220_request { @@ -70,9 +70,6 @@ static LIST_HEAD(sclp_vt220_empty); /* List of pending requests */ static LIST_HEAD(sclp_vt220_outqueue); -/* Suspend mode flag */ -static int sclp_vt220_suspended; - /* Flag that output queue is currently running */ static int sclp_vt220_queue_running; @@ -96,15 +93,12 @@ static int __initdata sclp_vt220_init_count; static int sclp_vt220_flush_later; static void sclp_vt220_receiver_fn(struct evbuf_header *evbuf); -static void sclp_vt220_pm_event_fn(struct sclp_register *reg, - enum sclp_pm_event sclp_pm_event); static int __sclp_vt220_emit(struct sclp_vt220_request *request); static void sclp_vt220_emit_current(void); /* Registration structure for SCLP output event buffers */ static struct sclp_register sclp_vt220_register = { .send_mask = EVTYP_VT220MSG_MASK, - .pm_event_fn = sclp_vt220_pm_event_fn, }; /* Registration structure for SCLP input event buffers */ @@ -136,7 +130,7 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request) if (!list_empty(&sclp_vt220_outqueue)) request = list_entry(sclp_vt220_outqueue.next, struct sclp_vt220_request, list); - if (!request || sclp_vt220_suspended) { + if (!request) { sclp_vt220_queue_running = 0; spin_unlock_irqrestore(&sclp_vt220_lock, flags); break; @@ -242,7 +236,7 @@ sclp_vt220_emit_current(void) } sclp_vt220_flush_later = 0; } - if (sclp_vt220_queue_running || sclp_vt220_suspended) + if (sclp_vt220_queue_running) goto out_unlock; if (list_empty(&sclp_vt220_outqueue)) goto out_unlock; @@ -421,7 +415,7 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule, if (list_empty(&sclp_vt220_empty)) sclp_console_full++; while (list_empty(&sclp_vt220_empty)) { - if (may_fail || sclp_vt220_suspended) + if (may_fail) goto out; if (sclp_vt220_drop_buffer()) break; @@ -792,46 +786,6 @@ static void __sclp_vt220_flush_buffer(void) spin_unlock_irqrestore(&sclp_vt220_lock, flags); } -/* - * Resume console: If there are cached messages, emit them. - */ -static void sclp_vt220_resume(void) -{ - unsigned long flags; - - spin_lock_irqsave(&sclp_vt220_lock, flags); - sclp_vt220_suspended = 0; - spin_unlock_irqrestore(&sclp_vt220_lock, flags); - sclp_vt220_emit_current(); -} - -/* - * Suspend console: Set suspend flag and flush console - */ -static void sclp_vt220_suspend(void) -{ - unsigned long flags; - - spin_lock_irqsave(&sclp_vt220_lock, flags); - sclp_vt220_suspended = 1; - spin_unlock_irqrestore(&sclp_vt220_lock, flags); - __sclp_vt220_flush_buffer(); -} - -static void sclp_vt220_pm_event_fn(struct sclp_register *reg, - enum sclp_pm_event sclp_pm_event) -{ - switch (sclp_pm_event) { - case SCLP_PM_EVENT_FREEZE: - sclp_vt220_suspend(); - break; - case SCLP_PM_EVENT_RESTORE: - case SCLP_PM_EVENT_THAW: - sclp_vt220_resume(); - break; - } -} - #ifdef CONFIG_SCLP_VT220_CONSOLE static void diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index 58333cb4503f..ed970ecfafdf 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -679,34 +679,10 @@ static const struct attribute_group *vmlogrdr_attr_groups[] = { NULL, }; -static int vmlogrdr_pm_prepare(struct device *dev) -{ - int rc; - struct vmlogrdr_priv_t *priv = dev_get_drvdata(dev); - - rc = 0; - if (priv) { - spin_lock_bh(&priv->priv_lock); - if (priv->dev_in_use) - rc = -EBUSY; - spin_unlock_bh(&priv->priv_lock); - } - if (rc) - pr_err("vmlogrdr: device %s is busy. Refuse to suspend.\n", - dev_name(dev)); - return rc; -} - - -static const struct dev_pm_ops vmlogrdr_pm_ops = { - .prepare = vmlogrdr_pm_prepare, -}; - static struct class *vmlogrdr_class; static struct device_driver vmlogrdr_driver = { .name = "vmlogrdr", .bus = &iucv_bus, - .pm = &vmlogrdr_pm_ops, .groups = vmlogrdr_drv_attr_groups, }; diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index cb466ed7eb5e..e56535c99888 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -93,7 +93,7 @@ static irqreturn_t do_airq_interrupt(int irq, void *dummy) struct hlist_head *head; set_cpu_flag(CIF_NOHZ_DELAY); - tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; + tpi_info = &get_irq_regs()->tpi_info; trace_s390_cio_adapter_int(tpi_info); head = &airq_lists[tpi_info->isc]; rcu_read_lock(); diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 444385da5792..9748165e08e9 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -45,27 +45,6 @@ static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) } } -/* - * Remove references from ccw devices to ccw group device and from - * ccw group device to ccw devices. - */ -static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev) -{ - struct ccw_device *cdev; - int i; - - for (i = 0; i < gdev->count; i++) { - cdev = gdev->cdev[i]; - if (!cdev) - continue; - spin_lock_irq(cdev->ccwlock); - dev_set_drvdata(&cdev->dev, NULL); - spin_unlock_irq(cdev->ccwlock); - gdev->cdev[i] = NULL; - put_device(&cdev->dev); - } -} - /** * ccwgroup_set_online() - enable a ccwgroup device * @gdev: target ccwgroup device @@ -175,7 +154,6 @@ static void ccwgroup_ungroup(struct ccwgroup_device *gdev) if (device_is_registered(&gdev->dev)) { __ccwgroup_remove_symlinks(gdev); device_unregister(&gdev->dev); - __ccwgroup_remove_cdev_refs(gdev); } mutex_unlock(&gdev->reg_mutex); } @@ -228,7 +206,23 @@ static void ccwgroup_ungroup_workfn(struct work_struct *work) static void ccwgroup_release(struct device *dev) { - kfree(to_ccwgroupdev(dev)); + struct ccwgroup_device *gdev = to_ccwgroupdev(dev); + unsigned int i; + + for (i = 0; i < gdev->count; i++) { + struct ccw_device *cdev = gdev->cdev[i]; + unsigned long flags; + + if (cdev) { + spin_lock_irqsave(cdev->ccwlock, flags); + if (dev_get_drvdata(&cdev->dev) == gdev) + dev_set_drvdata(&cdev->dev, NULL); + spin_unlock_irqrestore(cdev->ccwlock, flags); + put_device(&cdev->dev); + } + } + + kfree(gdev); } static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) @@ -396,15 +390,6 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, mutex_unlock(&gdev->reg_mutex); return 0; error: - for (i = 0; i < num_devices; i++) - if (gdev->cdev[i]) { - spin_lock_irq(gdev->cdev[i]->ccwlock); - if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) - dev_set_drvdata(&gdev->cdev[i]->dev, NULL); - spin_unlock_irq(gdev->cdev[i]->ccwlock); - put_device(&gdev->cdev[i]->dev); - gdev->cdev[i] = NULL; - } mutex_unlock(&gdev->reg_mutex); put_device(&gdev->dev); return rc; @@ -416,7 +401,7 @@ static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, { struct ccwgroup_device *gdev = to_ccwgroupdev(data); - if (action == BUS_NOTIFY_UNBIND_DRIVER) { + if (action == BUS_NOTIFY_UNBOUND_DRIVER) { get_device(&gdev->dev); schedule_work(&gdev->ungroup_work); } @@ -514,15 +499,6 @@ EXPORT_SYMBOL(ccwgroup_driver_register); */ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) { - struct device *dev; - - /* We don't want ccwgroup devices to live longer than their driver. */ - while ((dev = driver_find_next_device(&cdriver->driver, NULL))) { - struct ccwgroup_device *gdev = to_ccwgroupdev(dev); - - ccwgroup_ungroup(gdev); - put_device(dev); - } driver_unregister(&cdriver->driver); } EXPORT_SYMBOL(ccwgroup_driver_unregister); diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index e42113825415..1097e76982a5 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -255,6 +255,9 @@ static ssize_t chp_status_write(struct device *dev, if (!num_args) return count; + /* Wait until previous actions have settled. */ + css_wait_for_slow_path(); + if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) { mutex_lock(&cp->lock); error = s390_vary_chpid(cp->chpid, 1); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index c22d9ee27ba1..297fb399363c 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -801,8 +801,6 @@ int chsc_chp_vary(struct chp_id chpid, int on) { struct channel_path *chp = chpid_to_chp(chpid); - /* Wait until previous actions have settled. */ - css_wait_for_slow_path(); /* * Redo PathVerification on the devices the chpid connects to */ diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 6d716db2a46a..923f5ca4f5e6 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -536,7 +536,7 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy) struct irb *irb; set_cpu_flag(CIF_NOHZ_DELAY); - tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; + tpi_info = &get_irq_regs()->tpi_info; trace_s390_cio_interrupt(tpi_info); irb = this_cpu_ptr(&cio_irb); sch = (struct subchannel *)(unsigned long) tpi_info->intparm; diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index dcdaba689b20..1cb9daf9c645 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -9,6 +9,7 @@ #include <asm/cio.h> #include <asm/fcx.h> #include <asm/schid.h> +#include <asm/tpi.h> #include "chsc.h" /* @@ -46,18 +47,6 @@ struct pmcw { /* ... in an operand exception. */ } __attribute__ ((packed)); -/* I/O-Interruption Code as stored by TEST PENDING INTERRUPTION (TPI). */ -struct tpi_info { - struct subchannel_id schid; - u32 intparm; - u32 adapter_IO:1; - u32 directed_irq:1; - u32 isc:3; - u32 :27; - u32 type:3; - u32 :12; -} __packed __aligned(4); - /* Target SCHIB configuration. */ struct schib_config { u64 mba; diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index b7b590646d58..5584aa46c94e 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -163,13 +163,14 @@ static inline u64 time_to_avg_nsec(u32 value, u32 count) */ static inline void cmf_activate(void *area, unsigned int onoff) { - register void * __gpr2 asm("2"); - register long __gpr1 asm("1"); - - __gpr2 = area; - __gpr1 = onoff; /* activate channel measurement */ - asm("schm" : : "d" (__gpr2), "d" (__gpr1) ); + asm volatile( + " lgr 1,%[r1]\n" + " lgr 2,%[mbo]\n" + " schm\n" + : + : [r1] "d" ((unsigned long)onoff), [mbo] "d" (area) + : "1", "2"); } static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, diff --git a/drivers/s390/cio/ioasm.c b/drivers/s390/cio/ioasm.c index 4c5244d6052b..180913007824 100644 --- a/drivers/s390/cio/ioasm.c +++ b/drivers/s390/cio/ioasm.c @@ -16,18 +16,19 @@ static inline int __stsch(struct subchannel_id schid, struct schib *addr) { - register struct subchannel_id reg1 asm ("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode = -EIO; asm volatile( - " stsch 0(%3)\n" - "0: ipm %0\n" - " srl %0,28\n" + " lgr 1,%[r1]\n" + " stsch %[addr]\n" + "0: ipm %[cc]\n" + " srl %[cc],28\n" "1:\n" EX_TABLE(0b, 1b) - : "+d" (ccode), "=m" (*addr) - : "d" (reg1), "a" (addr) - : "cc"); + : [cc] "+&d" (ccode), [addr] "=Q" (*addr) + : [r1] "d" (r1) + : "cc", "1"); return ccode; } @@ -44,18 +45,19 @@ EXPORT_SYMBOL(stsch); static inline int __msch(struct subchannel_id schid, struct schib *addr) { - register struct subchannel_id reg1 asm ("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode = -EIO; asm volatile( - " msch 0(%2)\n" - "0: ipm %0\n" - " srl %0,28\n" + " lgr 1,%[r1]\n" + " msch %[addr]\n" + "0: ipm %[cc]\n" + " srl %[cc],28\n" "1:\n" EX_TABLE(0b, 1b) - : "+d" (ccode) - : "d" (reg1), "a" (addr), "m" (*addr) - : "cc"); + : [cc] "+&d" (ccode) + : [r1] "d" (r1), [addr] "Q" (*addr) + : "cc", "1"); return ccode; } @@ -71,16 +73,17 @@ int msch(struct subchannel_id schid, struct schib *addr) static inline int __tsch(struct subchannel_id schid, struct irb *addr) { - register struct subchannel_id reg1 asm ("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode; asm volatile( - " tsch 0(%3)\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode), "=m" (*addr) - : "d" (reg1), "a" (addr) - : "cc"); + " lgr 1,%[r1]\n" + " tsch %[addr]\n" + " ipm %[cc]\n" + " srl %[cc],28" + : [cc] "=&d" (ccode), [addr] "=Q" (*addr) + : [r1] "d" (r1) + : "cc", "1"); return ccode; } @@ -96,18 +99,19 @@ int tsch(struct subchannel_id schid, struct irb *addr) static inline int __ssch(struct subchannel_id schid, union orb *addr) { - register struct subchannel_id reg1 asm("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode = -EIO; asm volatile( - " ssch 0(%2)\n" - "0: ipm %0\n" - " srl %0,28\n" + " lgr 1,%[r1]\n" + " ssch %[addr]\n" + "0: ipm %[cc]\n" + " srl %[cc],28\n" "1:\n" EX_TABLE(0b, 1b) - : "+d" (ccode) - : "d" (reg1), "a" (addr), "m" (*addr) - : "cc", "memory"); + : [cc] "+&d" (ccode) + : [r1] "d" (r1), [addr] "Q" (*addr) + : "cc", "memory", "1"); return ccode; } @@ -124,16 +128,17 @@ EXPORT_SYMBOL(ssch); static inline int __csch(struct subchannel_id schid) { - register struct subchannel_id reg1 asm("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode; asm volatile( + " lgr 1,%[r1]\n" " csch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (ccode) + : [r1] "d" (r1) + : "cc", "1"); return ccode; } @@ -153,11 +158,11 @@ int tpi(struct tpi_info *addr) int ccode; asm volatile( - " tpi 0(%2)\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode), "=m" (*addr) - : "a" (addr) + " tpi %[addr]\n" + " ipm %[cc]\n" + " srl %[cc],28" + : [cc] "=&d" (ccode), [addr] "=Q" (*addr) + : : "cc"); trace_s390_cio_tpi(addr, ccode); @@ -170,13 +175,13 @@ int chsc(void *chsc_area) int cc = -EIO; asm volatile( - " .insn rre,0xb25f0000,%2,0\n" - "0: ipm %0\n" - " srl %0,28\n" + " .insn rre,0xb25f0000,%[chsc_area],0\n" + "0: ipm %[cc]\n" + " srl %[cc],28\n" "1:\n" EX_TABLE(0b, 1b) - : "+d" (cc), "=m" (*(addr_type *) chsc_area) - : "d" (chsc_area), "m" (*(addr_type *) chsc_area) + : [cc] "+&d" (cc), "+m" (*(addr_type *)chsc_area) + : [chsc_area] "d" (chsc_area) : "cc"); trace_s390_cio_chsc(chsc_area, cc); @@ -186,17 +191,17 @@ EXPORT_SYMBOL(chsc); static inline int __rsch(struct subchannel_id schid) { - register struct subchannel_id reg1 asm("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode; asm volatile( + " lgr 1,%[r1]\n" " rsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc", "memory"); - + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (ccode) + : [r1] "d" (r1) + : "cc", "memory", "1"); return ccode; } @@ -212,16 +217,17 @@ int rsch(struct subchannel_id schid) static inline int __hsch(struct subchannel_id schid) { - register struct subchannel_id reg1 asm("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode; asm volatile( + " lgr 1,%[r1]\n" " hsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (ccode) + : [r1] "d" (r1) + : "cc", "1"); return ccode; } @@ -238,16 +244,17 @@ EXPORT_SYMBOL(hsch); static inline int __xsch(struct subchannel_id schid) { - register struct subchannel_id reg1 asm("1") = schid; + unsigned long r1 = *(unsigned int *)&schid; int ccode; asm volatile( + " lgr 1,%[r1]\n" " xsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (ccode) + : [r1] "d" (r1) + : "cc", "1"); return ccode; } @@ -266,11 +273,11 @@ static inline int __stcrw(struct crw *crw) int ccode; asm volatile( - " stcrw 0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (ccode), "=m" (*crw) - : "a" (crw) + " stcrw %[crw]\n" + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (ccode), [crw] "=Q" (*crw) + : : "cc"); return ccode; } diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 0e0044d70844..f69ffbb8edc9 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -88,15 +88,15 @@ enum qdio_irq_states { static inline int do_sqbs(u64 token, unsigned char state, int queue, int *start, int *count) { - register unsigned long _ccq asm ("0") = *count; - register unsigned long _token asm ("1") = token; unsigned long _queuestart = ((unsigned long)queue << 32) | *start; + unsigned long _ccq = *count; asm volatile( - " .insn rsy,0xeb000000008A,%1,0,0(%2)" - : "+d" (_ccq), "+d" (_queuestart) - : "d" ((unsigned long)state), "d" (_token) - : "memory", "cc"); + " lgr 1,%[token]\n" + " .insn rsy,0xeb000000008a,%[qs],%[ccq],0(%[state])" + : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart) + : [state] "d" ((unsigned long)state), [token] "d" (token) + : "memory", "cc", "1"); *count = _ccq & 0xff; *start = _queuestart & 0xff; @@ -106,16 +106,17 @@ static inline int do_sqbs(u64 token, unsigned char state, int queue, static inline int do_eqbs(u64 token, unsigned char *state, int queue, int *start, int *count, int ack) { - register unsigned long _ccq asm ("0") = *count; - register unsigned long _token asm ("1") = token; unsigned long _queuestart = ((unsigned long)queue << 32) | *start; unsigned long _state = (unsigned long)ack << 63; + unsigned long _ccq = *count; asm volatile( - " .insn rrf,0xB99c0000,%1,%2,0,0" - : "+d" (_ccq), "+d" (_queuestart), "+d" (_state) - : "d" (_token) - : "memory", "cc"); + " lgr 1,%[token]\n" + " .insn rrf,0xb99c0000,%[qs],%[state],%[ccq],0" + : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart), + [state] "+&d" (_state) + : [token] "d" (token) + : "memory", "cc", "1"); *count = _ccq & 0xff; *start = _queuestart & 0xff; *state = _state & 0xff; diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 307ce7ff5ca4..3052fab00597 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -31,38 +31,41 @@ MODULE_DESCRIPTION("QDIO base support"); MODULE_LICENSE("GPL"); static inline int do_siga_sync(unsigned long schid, - unsigned int out_mask, unsigned int in_mask, + unsigned long out_mask, unsigned long in_mask, unsigned int fc) { - register unsigned long __fc asm ("0") = fc; - register unsigned long __schid asm ("1") = schid; - register unsigned long out asm ("2") = out_mask; - register unsigned long in asm ("3") = in_mask; int cc; asm volatile( + " lgr 0,%[fc]\n" + " lgr 1,%[schid]\n" + " lgr 2,%[out]\n" + " lgr 3,%[in]\n" " siga 0\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc) - : "d" (__fc), "d" (__schid), "d" (out), "d" (in) : "cc"); + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (cc) + : [fc] "d" (fc), [schid] "d" (schid), + [out] "d" (out_mask), [in] "d" (in_mask) + : "cc", "0", "1", "2", "3"); return cc; } -static inline int do_siga_input(unsigned long schid, unsigned int mask, - unsigned int fc) +static inline int do_siga_input(unsigned long schid, unsigned long mask, + unsigned long fc) { - register unsigned long __fc asm ("0") = fc; - register unsigned long __schid asm ("1") = schid; - register unsigned long __mask asm ("2") = mask; int cc; asm volatile( + " lgr 0,%[fc]\n" + " lgr 1,%[schid]\n" + " lgr 2,%[mask]\n" " siga 0\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc) - : "d" (__fc), "d" (__schid), "d" (__mask) : "cc"); + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (cc) + : [fc] "d" (fc), [schid] "d" (schid), [mask] "d" (mask) + : "cc", "0", "1", "2"); return cc; } @@ -78,23 +81,24 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask, * Note: For IQDC unicast queues only the highest priority queue is processed. */ static inline int do_siga_output(unsigned long schid, unsigned long mask, - unsigned int *bb, unsigned int fc, + unsigned int *bb, unsigned long fc, unsigned long aob) { - register unsigned long __fc asm("0") = fc; - register unsigned long __schid asm("1") = schid; - register unsigned long __mask asm("2") = mask; - register unsigned long __aob asm("3") = aob; int cc; asm volatile( + " lgr 0,%[fc]\n" + " lgr 1,%[schid]\n" + " lgr 2,%[mask]\n" + " lgr 3,%[aob]\n" " siga 0\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc), "+d" (__fc), "+d" (__aob) - : "d" (__schid), "d" (__mask) - : "cc"); - *bb = __fc >> 31; + " lgr %[fc],0\n" + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "=&d" (cc), [fc] "+&d" (fc) + : [schid] "d" (schid), [mask] "d" (mask), [aob] "d" (aob) + : "cc", "0", "1", "2", "3"); + *bb = fc >> 31; return cc; } diff --git a/drivers/s390/cio/trace.h b/drivers/s390/cio/trace.h index 4803139bce14..86993de25345 100644 --- a/drivers/s390/cio/trace.h +++ b/drivers/s390/cio/trace.h @@ -168,10 +168,8 @@ TRACE_EVENT(s390_cio_tpi, memset(&__entry->tpi_info, 0, sizeof(struct tpi_info)); else if (addr) __entry->tpi_info = *addr; - else { - memcpy(&__entry->tpi_info, &S390_lowcore.subchannel_id, - sizeof(struct tpi_info)); - } + else + __entry->tpi_info = S390_lowcore.tpi_info; __entry->cssid = __entry->tpi_info.schid.cssid; __entry->ssid = __entry->tpi_info.schid.ssid; __entry->schno = __entry->tpi_info.schid.sch_no; diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 2758d05a802d..d2560186d771 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright IBM Corp. 2006, 2020 + * Copyright IBM Corp. 2006, 2021 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com> * Ralph Wuerthner <rwuerthn@de.ibm.com> @@ -77,6 +77,9 @@ EXPORT_SYMBOL(ap_perms_mutex); /* # of bus scans since init */ static atomic64_t ap_scan_bus_count; +/* # of bindings complete since init */ +static atomic64_t ap_bindings_complete_count = ATOMIC64_INIT(0); + /* completion for initial APQN bindings complete */ static DECLARE_COMPLETION(ap_init_apqn_bindings_complete); @@ -584,22 +587,47 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv) */ static int ap_uevent(struct device *dev, struct kobj_uevent_env *env) { - int rc; + int rc = 0; struct ap_device *ap_dev = to_ap_dev(dev); /* Uevents from ap bus core don't need extensions to the env */ if (dev == ap_root_device) return 0; - /* Set up DEV_TYPE environment variable. */ - rc = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type); - if (rc) - return rc; + if (is_card_dev(dev)) { + struct ap_card *ac = to_ap_card(&ap_dev->device); - /* Add MODALIAS= */ - rc = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type); - if (rc) - return rc; + /* Set up DEV_TYPE environment variable. */ + rc = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type); + if (rc) + return rc; + /* Add MODALIAS= */ + rc = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type); + if (rc) + return rc; + + /* Add MODE=<accel|cca|ep11> */ + if (ap_test_bit(&ac->functions, AP_FUNC_ACCEL)) + rc = add_uevent_var(env, "MODE=accel"); + else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) + rc = add_uevent_var(env, "MODE=cca"); + else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) + rc = add_uevent_var(env, "MODE=ep11"); + if (rc) + return rc; + } else { + struct ap_queue *aq = to_ap_queue(&ap_dev->device); + + /* Add MODE=<accel|cca|ep11> */ + if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL)) + rc = add_uevent_var(env, "MODE=accel"); + else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) + rc = add_uevent_var(env, "MODE=cca"); + else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) + rc = add_uevent_var(env, "MODE=ep11"); + if (rc) + return rc; + } return 0; } @@ -613,11 +641,36 @@ static void ap_send_init_scan_done_uevent(void) static void ap_send_bindings_complete_uevent(void) { - char *envp[] = { "BINDINGS=complete", NULL }; + char buf[32]; + char *envp[] = { "BINDINGS=complete", buf, NULL }; + snprintf(buf, sizeof(buf), "COMPLETECOUNT=%llu", + atomic64_inc_return(&ap_bindings_complete_count)); kobject_uevent_env(&ap_root_device->kobj, KOBJ_CHANGE, envp); } +void ap_send_config_uevent(struct ap_device *ap_dev, bool cfg) +{ + char buf[16]; + char *envp[] = { buf, NULL }; + + snprintf(buf, sizeof(buf), "CONFIG=%d", cfg ? 1 : 0); + + kobject_uevent_env(&ap_dev->device.kobj, KOBJ_CHANGE, envp); +} +EXPORT_SYMBOL(ap_send_config_uevent); + +void ap_send_online_uevent(struct ap_device *ap_dev, int online) +{ + char buf[16]; + char *envp[] = { buf, NULL }; + + snprintf(buf, sizeof(buf), "ONLINE=%d", online ? 1 : 0); + + kobject_uevent_env(&ap_dev->device.kobj, KOBJ_CHANGE, envp); +} +EXPORT_SYMBOL(ap_send_online_uevent); + /* * calc # of bound APQNs */ @@ -885,8 +938,6 @@ int ap_driver_register(struct ap_driver *ap_drv, struct module *owner, struct device_driver *drv = &ap_drv->driver; drv->bus = &ap_bus_type; - drv->probe = ap_device_probe; - drv->remove = ap_device_remove; drv->owner = owner; drv->name = name; return driver_register(drv); @@ -1319,6 +1370,8 @@ static struct bus_type ap_bus_type = { .bus_groups = ap_bus_groups, .match = &ap_bus_match, .uevent = &ap_uevent, + .probe = ap_device_probe, + .remove = ap_device_remove, }; /** @@ -1540,6 +1593,7 @@ static inline void ap_scan_domains(struct ap_card *ac) spin_unlock_bh(&aq->lock); AP_DBF_INFO("%s(%d,%d) queue device config off\n", __func__, ac->id, dom); + ap_send_config_uevent(&aq->ap_dev, aq->config); /* 'receive' pending messages with -EAGAIN */ ap_flush_queue(aq); goto put_dev_and_continue; @@ -1554,6 +1608,7 @@ static inline void ap_scan_domains(struct ap_card *ac) spin_unlock_bh(&aq->lock); AP_DBF_INFO("%s(%d,%d) queue device config on\n", __func__, ac->id, dom); + ap_send_config_uevent(&aq->ap_dev, aq->config); goto put_dev_and_continue; } /* handle other error states */ @@ -1663,12 +1718,13 @@ static inline void ap_scan_adapter(int ap) ac->config = false; AP_DBF_INFO("%s(%d) card device config off\n", __func__, ap); - + ap_send_config_uevent(&ac->ap_dev, ac->config); } if (!decfg && !ac->config) { ac->config = true; AP_DBF_INFO("%s(%d) card device config on\n", __func__, ap); + ap_send_config_uevent(&ac->ap_dev, ac->config); } } } diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 472efd3a755c..230fec6510e2 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -362,4 +362,7 @@ int ap_parse_mask_str(const char *str, */ int ap_wait_init_apqn_bindings_complete(unsigned long timeout); +void ap_send_config_uevent(struct ap_device *ap_dev, bool cfg); +void ap_send_online_uevent(struct ap_device *ap_dev, int online); + #endif /* _AP_BUS_H_ */ diff --git a/drivers/s390/crypto/ap_card.c b/drivers/s390/crypto/ap_card.c index d98bdd28d23e..ca9afc5fcaf7 100644 --- a/drivers/s390/crypto/ap_card.c +++ b/drivers/s390/crypto/ap_card.c @@ -167,6 +167,8 @@ static ssize_t config_store(struct device *dev, ac->config = cfg ? true : false; + ap_send_config_uevent(&ac->ap_dev, ac->config); + return count; } diff --git a/drivers/s390/crypto/vfio_ap_drv.c b/drivers/s390/crypto/vfio_ap_drv.c index 7dc72cb718b0..4d2556bc7fe5 100644 --- a/drivers/s390/crypto/vfio_ap_drv.c +++ b/drivers/s390/crypto/vfio_ap_drv.c @@ -22,8 +22,6 @@ MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("VFIO AP device driver, Copyright IBM Corp. 2018"); MODULE_LICENSE("GPL v2"); -static struct ap_driver vfio_ap_drv; - struct ap_matrix_dev *matrix_dev; /* Only type 10 adapters (CEX4 and later) are supported @@ -80,6 +78,12 @@ static void vfio_ap_queue_dev_remove(struct ap_device *apdev) mutex_unlock(&matrix_dev->lock); } +static struct ap_driver vfio_ap_drv = { + .probe = vfio_ap_queue_dev_probe, + .remove = vfio_ap_queue_dev_remove, + .ids = ap_queue_ids, +}; + static void vfio_ap_matrix_dev_release(struct device *dev) { struct ap_matrix_dev *matrix_dev = dev_get_drvdata(dev); @@ -181,11 +185,6 @@ static int __init vfio_ap_init(void) if (ret) return ret; - memset(&vfio_ap_drv, 0, sizeof(vfio_ap_drv)); - vfio_ap_drv.probe = vfio_ap_queue_dev_probe; - vfio_ap_drv.remove = vfio_ap_queue_dev_remove; - vfio_ap_drv.ids = ap_queue_ids; - ret = ap_driver_register(&vfio_ap_drv, THIS_MODULE, VFIO_AP_DRV_NAME); if (ret) { vfio_ap_matrix_dev_destroy(); diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 52eaf51c9bb6..5d726cd67314 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -59,7 +59,6 @@ MODULE_PARM_DESC(hwrng_seed, "Turn on/off hwrng auto seed, default is 1 (on)."); DEFINE_SPINLOCK(zcrypt_list_lock); LIST_HEAD(zcrypt_card_list); -int zcrypt_device_count; static atomic_t zcrypt_open_count = ATOMIC_INIT(0); static atomic_t zcrypt_rescan_count = ATOMIC_INIT(0); diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 16219efb2f61..93e77e83ad14 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -124,7 +124,6 @@ struct zcrypt_queue { extern atomic_t zcrypt_rescan_req; extern spinlock_t zcrypt_list_lock; -extern int zcrypt_device_count; extern struct list_head zcrypt_card_list; #define for_each_zcrypt_card(_zc) \ @@ -146,7 +145,7 @@ void zcrypt_queue_get(struct zcrypt_queue *); int zcrypt_queue_put(struct zcrypt_queue *); int zcrypt_queue_register(struct zcrypt_queue *); void zcrypt_queue_unregister(struct zcrypt_queue *); -void zcrypt_queue_force_online(struct zcrypt_queue *, int); +bool zcrypt_queue_force_online(struct zcrypt_queue *zq, int online); int zcrypt_rng_device_add(void); void zcrypt_rng_device_remove(void); diff --git a/drivers/s390/crypto/zcrypt_card.c b/drivers/s390/crypto/zcrypt_card.c index 09fe6bb8880b..40fd5d37d26a 100644 --- a/drivers/s390/crypto/zcrypt_card.c +++ b/drivers/s390/crypto/zcrypt_card.c @@ -64,7 +64,8 @@ static ssize_t online_store(struct device *dev, struct ap_card *ac = to_ap_card(dev); struct zcrypt_card *zc = ac->private; struct zcrypt_queue *zq; - int online, id; + int online, id, i = 0, maxzqs = 0; + struct zcrypt_queue **zq_uelist = NULL; if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1) return -EINVAL; @@ -77,10 +78,35 @@ static ssize_t online_store(struct device *dev, ZCRYPT_DBF(DBF_INFO, "card=%02x online=%d\n", id, online); + ap_send_online_uevent(&ac->ap_dev, online); + spin_lock(&zcrypt_list_lock); + /* + * As we are in atomic context here, directly sending uevents + * does not work. So collect the zqueues in a dynamic array + * and process them after zcrypt_list_lock release. As we get/put + * the zqueue objects, we make sure they exist after lock release. + */ + list_for_each_entry(zq, &zc->zqueues, list) + maxzqs++; + if (maxzqs > 0) + zq_uelist = kcalloc(maxzqs + 1, sizeof(zq), GFP_ATOMIC); list_for_each_entry(zq, &zc->zqueues, list) - zcrypt_queue_force_online(zq, online); + if (zcrypt_queue_force_online(zq, online)) + if (zq_uelist) { + zcrypt_queue_get(zq); + zq_uelist[i++] = zq; + } spin_unlock(&zcrypt_list_lock); + if (zq_uelist) { + for (i = 0; zq_uelist[i]; i++) { + zq = zq_uelist[i]; + ap_send_online_uevent(&zq->queue->ap_dev, online); + zcrypt_queue_put(zq); + } + kfree(zq_uelist); + } + return count; } diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index d68c0ed5e0dd..bc34bedf9db8 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -295,7 +295,7 @@ static inline void prep_xcrb(struct ica_xcRB *pxcrb, * Generate (random) CCA AES DATA secure key. */ int cca_genseckey(u16 cardnr, u16 domain, - u32 keybitsize, u8 seckey[SECKEYBLOBSIZE]) + u32 keybitsize, u8 *seckey) { int i, rc, keysize; int seckeysize; @@ -330,7 +330,7 @@ int cca_genseckey(u16 cardnr, u16 domain, struct { u16 toklen; u16 tokattr; - u8 tok[0]; + u8 tok[]; /* ... some more data ... */ } keyblock; } lv3; @@ -438,7 +438,7 @@ EXPORT_SYMBOL(cca_genseckey); * Generate an CCA AES DATA secure key with given key value. */ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, - const u8 *clrkey, u8 seckey[SECKEYBLOBSIZE]) + const u8 *clrkey, u8 *seckey) { int rc, keysize, seckeysize; u8 *mem, *ptr; @@ -471,7 +471,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, struct { u16 toklen; u16 tokattr; - u8 tok[0]; + u8 tok[]; /* ... some more data ... */ } keyblock; } lv3; @@ -577,8 +577,8 @@ EXPORT_SYMBOL(cca_clr2seckey); * Derive proteced key from an CCA AES DATA secure key. */ int cca_sec2protkey(u16 cardnr, u16 domain, - const u8 seckey[SECKEYBLOBSIZE], - u8 *protkey, u32 *protkeylen, u32 *protkeytype) + const u8 *seckey, u8 *protkey, u32 *protkeylen, + u32 *protkeytype) { int rc; u8 *mem, *ptr; @@ -596,7 +596,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain, u16 len; u16 attr_len; u16 attr_flags; - u8 token[0]; /* cca secure key token */ + u8 token[]; /* cca secure key token */ } lv2; } __packed * preqparm; struct uskrepparm { diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h index e7105443d5cb..3513cd8ab9bc 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.h +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -171,8 +171,8 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, * Derive proteced key from an CCA AES DATA secure key. */ int cca_sec2protkey(u16 cardnr, u16 domain, - const u8 seckey[SECKEYBLOBSIZE], - u8 *protkey, u32 *protkeylen, u32 *protkeytype); + const u8 *seckey, u8 *protkey, u32 *protkeylen, + u32 *protkeytype); /* * Generate (random) CCA AES CIPHER secure key. diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c index bf14ee445f89..6d1800cb21df 100644 --- a/drivers/s390/crypto/zcrypt_msgtype50.c +++ b/drivers/s390/crypto/zcrypt_msgtype50.c @@ -375,6 +375,7 @@ static int convert_type80(struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), t80h->code); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } if (zq->zcard->user_space_type == ZCRYPT_CEX2A) @@ -412,6 +413,7 @@ static int convert_response_cex2a(struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) rtype); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } } diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index 307f90657d1d..da6b2bf779a8 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -675,6 +675,7 @@ static int convert_type86_ica(struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) service_rc, (int) service_rs); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } data = msg->text; @@ -820,6 +821,7 @@ static int convert_response_ica(struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) msg->hdr.type); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } } @@ -854,6 +856,7 @@ static int convert_response_xcrb(bool userspace, struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) msg->hdr.type); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } } @@ -883,6 +886,7 @@ static int convert_response_ep11_xcrb(bool userspace, struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) msg->hdr.type); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } } @@ -913,6 +917,7 @@ static int convert_response_rng(struct zcrypt_queue *zq, AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), (int) msg->hdr.type); + ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } } diff --git a/drivers/s390/crypto/zcrypt_queue.c b/drivers/s390/crypto/zcrypt_queue.c index c3ffbd26b73f..605904b86287 100644 --- a/drivers/s390/crypto/zcrypt_queue.c +++ b/drivers/s390/crypto/zcrypt_queue.c @@ -70,6 +70,8 @@ static ssize_t online_store(struct device *dev, AP_QID_QUEUE(zq->queue->qid), online); + ap_send_online_uevent(&aq->ap_dev, online); + if (!online) ap_flush_queue(zq->queue); return count; @@ -98,11 +100,15 @@ static const struct attribute_group zcrypt_queue_attr_group = { .attrs = zcrypt_queue_attrs, }; -void zcrypt_queue_force_online(struct zcrypt_queue *zq, int online) +bool zcrypt_queue_force_online(struct zcrypt_queue *zq, int online) { - zq->online = online; - if (!online) - ap_flush_queue(zq->queue); + if (!!zq->online != !!online) { + zq->online = online; + if (!online) + ap_flush_queue(zq->queue); + return true; + } + return false; } struct zcrypt_queue *zcrypt_queue_alloc(size_t max_response_size) @@ -173,7 +179,6 @@ int zcrypt_queue_register(struct zcrypt_queue *zq) AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid)); list_add_tail(&zq->list, &zc->zqueues); - zcrypt_device_count++; spin_unlock(&zcrypt_list_lock); rc = sysfs_create_group(&zq->queue->ap_dev.device.kobj, @@ -216,7 +221,6 @@ void zcrypt_queue_unregister(struct zcrypt_queue *zq) zc = zq->zcard; spin_lock(&zcrypt_list_lock); list_del_init(&zq->list); - zcrypt_device_count--; spin_unlock(&zcrypt_list_lock); if (zq->ops->rng) zcrypt_rng_device_remove(); diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 54e686dca6de..d35e7a3f7067 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -388,31 +388,6 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev, ccw_device_dma_free(vcdev->cdev, thinint_area, sizeof(*thinint_area)); } -static inline long __do_kvm_notify(struct subchannel_id schid, - unsigned long queue_index, - long cookie) -{ - register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY; - register struct subchannel_id __schid asm("2") = schid; - register unsigned long __index asm("3") = queue_index; - register long __rc asm("2"); - register long __cookie asm("4") = cookie; - - asm volatile ("diag 2,4,0x500\n" - : "=d" (__rc) : "d" (__nr), "d" (__schid), "d" (__index), - "d"(__cookie) - : "memory", "cc"); - return __rc; -} - -static inline long do_kvm_notify(struct subchannel_id schid, - unsigned long queue_index, - long cookie) -{ - diag_stat_inc(DIAG_STAT_X500); - return __do_kvm_notify(schid, queue_index, cookie); -} - static bool virtio_ccw_kvm_notify(struct virtqueue *vq) { struct virtio_ccw_vq_info *info = vq->priv; @@ -421,7 +396,10 @@ static bool virtio_ccw_kvm_notify(struct virtqueue *vq) vcdev = to_vc_device(info->vq->vdev); ccw_device_get_schid(vcdev->cdev, &schid); - info->cookie = do_kvm_notify(schid, vq->index, info->cookie); + BUILD_BUG_ON(sizeof(struct subchannel_id) != sizeof(unsigned int)); + info->cookie = kvm_hypercall3(KVM_S390_VIRTIO_CCW_NOTIFY, + *((unsigned int *)&schid), + vq->index, info->cookie); if (info->cookie < 0) return false; return true; diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c index 2af1e5751bd6..297fa7b38b65 100644 --- a/drivers/tty/hvc/hvc_iucv.c +++ b/drivers/tty/hvc/hvc_iucv.c @@ -966,37 +966,6 @@ static void hvc_iucv_msg_complete(struct iucv_path *path, destroy_tty_buffer_list(&list_remove); } -/** - * hvc_iucv_pm_freeze() - Freeze PM callback - * @dev: IUVC HVC terminal device - * - * Sever an established IUCV communication path and - * trigger a hang-up of the underlying HVC terminal. - */ -static int hvc_iucv_pm_freeze(struct device *dev) -{ - struct hvc_iucv_private *priv = dev_get_drvdata(dev); - - local_bh_disable(); - hvc_iucv_hangup(priv); - local_bh_enable(); - - return 0; -} - -/** - * hvc_iucv_pm_restore_thaw() - Thaw and restore PM callback - * @dev: IUVC HVC terminal device - * - * Wake up the HVC thread to trigger hang-up and respective - * HVC back-end notifier invocations. - */ -static int hvc_iucv_pm_restore_thaw(struct device *dev) -{ - hvc_kick(); - return 0; -} - static ssize_t hvc_iucv_dev_termid_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1051,20 +1020,6 @@ static const struct hv_ops hvc_iucv_ops = { .dtr_rts = hvc_iucv_dtr_rts, }; -/* Suspend / resume device operations */ -static const struct dev_pm_ops hvc_iucv_pm_ops = { - .freeze = hvc_iucv_pm_freeze, - .thaw = hvc_iucv_pm_restore_thaw, - .restore = hvc_iucv_pm_restore_thaw, -}; - -/* IUCV HVC device driver */ -static struct device_driver hvc_iucv_driver = { - .name = KMSG_COMPONENT, - .bus = &iucv_bus, - .pm = &hvc_iucv_pm_ops, -}; - /* IUCV HVC device attributes */ static DEVICE_ATTR(termid, 0640, hvc_iucv_dev_termid_show, NULL); static DEVICE_ATTR(state, 0640, hvc_iucv_dev_state_show, NULL); @@ -1144,7 +1099,6 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console) dev_set_drvdata(priv->dev, priv); priv->dev->bus = &iucv_bus; priv->dev->parent = iucv_root; - priv->dev->driver = &hvc_iucv_driver; priv->dev->groups = hvc_iucv_dev_attr_groups; priv->dev->release = (void (*)(struct device *)) kfree; rc = device_register(priv->dev); @@ -1376,11 +1330,6 @@ static int __init hvc_iucv_init(void) goto out_error; } - /* register IUCV HVC device driver */ - rc = driver_register(&hvc_iucv_driver); - if (rc) - goto out_error; - /* parse hvc_iucv_allow string and create z/VM user ID filter list */ if (hvc_iucv_filter_string) { rc = hvc_iucv_setup_filter(hvc_iucv_filter_string); |