From: Martin Schwidefsky Date: Fri, 24 May 2013 10:30:03 +0000 (+0200) Subject: s390,sclp: add parameter to specify number of buffer pages X-Git-Tag: next-20130617~103^2~13 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=ada843c655b0e831134809c9c9798c5a28b83555;p=karo-tx-linux.git s390,sclp: add parameter to specify number of buffer pages Add a kernel parameter to be able to specify the number of pages to be used as output buffer by the line-mode sclp driver and the vt220 sclp driver. The current number of output pages is 6, if the service element is unavailable the boot messages alone can fill up the output buffer. If this happens the system blocks until the service element is working again. For a large LPAR with many devices it is sensible to have the ability to increase the output buffer size. To help to debug this situation add a counter for the page-pool-empty situation and make it available as a sclp driver attribute. Signed-off-by: Martin Schwidefsky --- diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index bd6871bf545a..723f657cce94 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -50,6 +50,23 @@ static char sclp_init_sccb[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); /* 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; +/* Number of times the console pages pool run empty */ +unsigned long sclp_console_pages_empty; + +static int __init sclp_setup_console_pages(char *str) +{ + int pages; + + pages = simple_strtoul(str, &str, 0); + if (pages >= 6) + sclp_console_pages = pages; + return 1; +} + +__setup("sclp_console_pages=", sclp_setup_console_pages); + static void sclp_suspend_req_cb(struct sclp_req *req, void *data) { complete(&sclp_request_queue_flushed); @@ -1013,11 +1030,41 @@ static const struct dev_pm_ops sclp_pm_ops = { .restore = sclp_restore, }; +static ssize_t sclp_show_console_pages(struct device_driver *dev, char *buf) +{ + return sprintf(buf, "%i\n", sclp_console_pages); +} + +static DRIVER_ATTR(console_pages, S_IRUSR, sclp_show_console_pages, NULL); + +static ssize_t sclp_show_console_pages_empty(struct device_driver *dev, + char *buf) +{ + return sprintf(buf, "%lu\n", sclp_console_pages_empty); +} + +static DRIVER_ATTR(console_pages_empty, S_IRUSR, + sclp_show_console_pages_empty, NULL); + +static struct attribute *sclp_drv_attrs[] = { + &driver_attr_console_pages.attr, + &driver_attr_console_pages_empty.attr, + NULL, +}; +static struct attribute_group sclp_drv_attr_group = { + .attrs = sclp_drv_attrs, +}; +static const struct attribute_group *sclp_drv_attr_groups[] = { + &sclp_drv_attr_group, + NULL, +}; + static struct platform_driver sclp_pdrv = { .driver = { .name = "sclp", .owner = THIS_MODULE, .pm = &sclp_pm_ops, + .groups = sclp_drv_attr_groups, }, }; @@ -1096,10 +1143,12 @@ static __init int sclp_initcall(void) rc = platform_driver_register(&sclp_pdrv); if (rc) return rc; + sclp_pdev = platform_device_register_simple("sclp", -1, NULL, 0); rc = IS_ERR(sclp_pdev) ? PTR_ERR(sclp_pdev) : 0; if (rc) goto fail_platform_driver_unregister; + rc = atomic_notifier_chain_register(&panic_notifier_list, &sclp_on_panic_nb); if (rc) diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 25bcd4c0ed82..d35495076ab6 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -15,7 +15,7 @@ /* maximum number of pages concerning our own memory management */ #define MAX_KMEM_PAGES (sizeof(unsigned long) << 3) -#define MAX_CONSOLE_PAGES 6 +#define SCLP_CONSOLE_PAGES 6 #define EVTYP_OPCMD 0x01 #define EVTYP_MSG 0x02 @@ -175,6 +175,9 @@ int sclp_service_call(sclp_cmdw_t command, void *sccb); int sclp_sdias_init(void); void sclp_sdias_exit(void); +extern int sclp_console_pages; +extern unsigned long sclp_console_pages_empty; + /* useful inlines */ /* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */ diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index ecf45c54f8c4..8e4639f439a1 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c @@ -150,6 +150,8 @@ sclp_console_write(struct console *console, const char *message, do { /* make sure we have a console output buffer */ if (sclp_conbuf == NULL) { + if (list_empty(&sclp_con_pages)) + sclp_console_pages_empty++; while (list_empty(&sclp_con_pages)) { if (sclp_con_suspended) goto out; @@ -297,7 +299,7 @@ sclp_console_init(void) return rc; /* Allocate pages for output buffering */ INIT_LIST_HEAD(&sclp_con_pages); - for (i = 0; i < MAX_CONSOLE_PAGES; i++) { + for (i = 0; i < sclp_console_pages; i++) { page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); list_add_tail(page, &sclp_con_pages); } diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 5aaaa2ec8df4..1953b1eb8ae0 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -390,6 +390,8 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule, do { /* Create an sclp output buffer if none exists yet */ if (sclp_vt220_current_request == NULL) { + if (list_empty(&sclp_vt220_empty)) + sclp_console_pages_empty++; while (list_empty(&sclp_vt220_empty)) { spin_unlock_irqrestore(&sclp_vt220_lock, flags); if (may_fail || sclp_vt220_suspended) @@ -803,7 +805,7 @@ sclp_vt220_con_init(void) if (!CONSOLE_IS_SCLP) return 0; - rc = __sclp_vt220_init(MAX_CONSOLE_PAGES); + rc = __sclp_vt220_init(sclp_console_pages); if (rc) return rc; /* Attach linux console */