aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2013-04-13 07:01:50 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-04-17 08:07:32 -0400
commit863fc8492734822b95671780db803cd9a4b7d923 (patch)
treebadeeb42bc2f1d047849882aecd37fffef91ca20 /drivers/s390/cio
parentc135ad1caffe2b35d6316758a605a2b63ca22bb3 (diff)
s390/cio: get rid of static console subchannel
Remove the static console subchannel (and friends) and use dynamic allocation for these structures. With this change the console subchanel is treated (mostly) like any other subchannel and we can remove some special cases. Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/cio.c111
-rw-r--r--drivers/s390/cio/cio.h5
-rw-r--r--drivers/s390/cio/css.c23
-rw-r--r--drivers/s390/cio/css.h1
-rw-r--r--drivers/s390/cio/device.c24
5 files changed, 56 insertions, 108 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 2c1d53fb2fab..ab99500604b7 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -540,13 +540,9 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
540 memset(sch, 0, sizeof(struct subchannel)); 540 memset(sch, 0, sizeof(struct subchannel));
541 541
542 sch->schid = schid; 542 sch->schid = schid;
543 if (cio_is_console(schid)) { 543 err = cio_create_sch_lock(sch);
544 sch->lock = cio_get_console_lock(); 544 if (err)
545 } else { 545 goto out;
546 err = cio_create_sch_lock(sch);
547 if (err)
548 goto out;
549 }
550 mutex_init(&sch->reg_mutex); 546 mutex_init(&sch->reg_mutex);
551 547
552 /* 548 /*
@@ -580,8 +576,7 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
580 sch->schid.ssid, sch->schid.sch_no, sch->st); 576 sch->schid.ssid, sch->schid.sch_no, sch->st);
581 return 0; 577 return 0;
582out: 578out:
583 if (!cio_is_console(schid)) 579 kfree(sch->lock);
584 kfree(sch->lock);
585 sch->lock = NULL; 580 sch->lock = NULL;
586 return err; 581 return err;
587} 582}
@@ -650,9 +645,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
650} 645}
651 646
652#ifdef CONFIG_CCW_CONSOLE 647#ifdef CONFIG_CCW_CONSOLE
653static struct subchannel console_subchannel; 648static struct subchannel *console_sch;
654static struct io_subchannel_private console_priv;
655static int console_subchannel_in_use;
656 649
657/* 650/*
658 * Use cio_tsch to update the subchannel status and call the interrupt handler 651 * Use cio_tsch to update the subchannel status and call the interrupt handler
@@ -685,119 +678,83 @@ void cio_tsch(struct subchannel *sch)
685 } 678 }
686} 679}
687 680
688void *cio_get_console_priv(void) 681static int cio_test_for_console(struct subchannel_id schid, void *data)
689{ 682{
690 return &console_priv; 683 struct schib schib;
691}
692 684
693static int 685 if (stsch_err(schid, &schib) != 0)
694cio_test_for_console(struct subchannel_id schid, void *data)
695{
696 if (stsch_err(schid, &console_subchannel.schib) != 0)
697 return -ENXIO; 686 return -ENXIO;
698 if ((console_subchannel.schib.pmcw.st == SUBCHANNEL_TYPE_IO) && 687 if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv &&
699 console_subchannel.schib.pmcw.dnv && 688 (schib.pmcw.dev == console_devno)) {
700 (console_subchannel.schib.pmcw.dev == console_devno)) {
701 console_irq = schid.sch_no; 689 console_irq = schid.sch_no;
702 return 1; /* found */ 690 return 1; /* found */
703 } 691 }
704 return 0; 692 return 0;
705} 693}
706 694
707 695static int cio_get_console_sch_no(void)
708static int
709cio_get_console_sch_no(void)
710{ 696{
711 struct subchannel_id schid; 697 struct subchannel_id schid;
712 698 struct schib schib;
699
713 init_subchannel_id(&schid); 700 init_subchannel_id(&schid);
714 if (console_irq != -1) { 701 if (console_irq != -1) {
715 /* VM provided us with the irq number of the console. */ 702 /* VM provided us with the irq number of the console. */
716 schid.sch_no = console_irq; 703 schid.sch_no = console_irq;
717 if (stsch_err(schid, &console_subchannel.schib) != 0 || 704 if (stsch_err(schid, &schib) != 0 ||
718 (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) || 705 (schib.pmcw.st != SUBCHANNEL_TYPE_IO) || !schib.pmcw.dnv)
719 !console_subchannel.schib.pmcw.dnv)
720 return -1; 706 return -1;
721 console_devno = console_subchannel.schib.pmcw.dev; 707 console_devno = schib.pmcw.dev;
722 } else if (console_devno != -1) { 708 } else if (console_devno != -1) {
723 /* At least the console device number is known. */ 709 /* At least the console device number is known. */
724 for_each_subchannel(cio_test_for_console, NULL); 710 for_each_subchannel(cio_test_for_console, NULL);
725 if (console_irq == -1)
726 return -1;
727 } else {
728 /* unlike in 2.4, we cannot autoprobe here, since
729 * the channel subsystem is not fully initialized.
730 * With some luck, the HWC console can take over */
731 return -1;
732 } 711 }
733 return console_irq; 712 return console_irq;
734} 713}
735 714
736struct subchannel * 715struct subchannel *cio_probe_console(void)
737cio_probe_console(void)
738{ 716{
739 int sch_no, ret;
740 struct subchannel_id schid; 717 struct subchannel_id schid;
718 struct subchannel *sch;
719 int sch_no, ret;
741 720
742 if (xchg(&console_subchannel_in_use, 1) != 0)
743 return ERR_PTR(-EBUSY);
744 sch_no = cio_get_console_sch_no(); 721 sch_no = cio_get_console_sch_no();
745 if (sch_no == -1) { 722 if (sch_no == -1) {
746 console_subchannel_in_use = 0;
747 pr_warning("No CCW console was found\n"); 723 pr_warning("No CCW console was found\n");
748 return ERR_PTR(-ENODEV); 724 return ERR_PTR(-ENODEV);
749 } 725 }
750 memset(&console_subchannel, 0, sizeof(struct subchannel));
751 init_subchannel_id(&schid); 726 init_subchannel_id(&schid);
752 schid.sch_no = sch_no; 727 schid.sch_no = sch_no;
753 ret = cio_validate_subchannel(&console_subchannel, schid); 728 sch = css_alloc_subchannel(schid);
754 if (ret) { 729 if (IS_ERR(sch))
755 console_subchannel_in_use = 0; 730 return sch;
756 return ERR_PTR(-ENODEV);
757 }
758 731
759 /*
760 * enable console I/O-interrupt subclass
761 */
762 isc_register(CONSOLE_ISC); 732 isc_register(CONSOLE_ISC);
763 console_subchannel.config.isc = CONSOLE_ISC; 733 sch->config.isc = CONSOLE_ISC;
764 console_subchannel.config.intparm = (u32)(addr_t)&console_subchannel; 734 sch->config.intparm = (u32)(addr_t)sch;
765 ret = cio_commit_config(&console_subchannel); 735 ret = cio_commit_config(sch);
766 if (ret) { 736 if (ret) {
767 isc_unregister(CONSOLE_ISC); 737 isc_unregister(CONSOLE_ISC);
768 console_subchannel_in_use = 0; 738 put_device(&sch->dev);
769 return ERR_PTR(ret); 739 return ERR_PTR(ret);
770 } 740 }
771 return &console_subchannel; 741 console_sch = sch;
772} 742 return sch;
773
774void
775cio_release_console(void)
776{
777 console_subchannel.config.intparm = 0;
778 cio_commit_config(&console_subchannel);
779 isc_unregister(CONSOLE_ISC);
780 console_subchannel_in_use = 0;
781} 743}
782 744
783/* Bah... hack to catch console special sausages. */ 745int cio_is_console(struct subchannel_id schid)
784int
785cio_is_console(struct subchannel_id schid)
786{ 746{
787 if (!console_subchannel_in_use) 747 if (!console_sch)
788 return 0; 748 return 0;
789 return schid_equal(&schid, &console_subchannel.schid); 749 return schid_equal(&schid, &console_sch->schid);
790} 750}
791 751
792struct subchannel * 752struct subchannel *cio_get_console_subchannel(void)
793cio_get_console_subchannel(void)
794{ 753{
795 if (!console_subchannel_in_use) 754 return console_sch;
796 return NULL;
797 return &console_subchannel;
798} 755}
756#endif /* CONFIG_CCW_CONSOLE */
799 757
800#endif
801static int 758static int
802__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) 759__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
803{ 760{
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 3b97c8bb30e5..78975471ef28 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -128,17 +128,12 @@ void do_IRQ(struct pt_regs *);
128/* Use with care. */ 128/* Use with care. */
129#ifdef CONFIG_CCW_CONSOLE 129#ifdef CONFIG_CCW_CONSOLE
130extern struct subchannel *cio_probe_console(void); 130extern struct subchannel *cio_probe_console(void);
131extern void cio_release_console(void);
132extern int cio_is_console(struct subchannel_id); 131extern int cio_is_console(struct subchannel_id);
133extern struct subchannel *cio_get_console_subchannel(void); 132extern struct subchannel *cio_get_console_subchannel(void);
134extern spinlock_t * cio_get_console_lock(void);
135extern void *cio_get_console_priv(void);
136extern void cio_tsch(struct subchannel *sch); 133extern void cio_tsch(struct subchannel *sch);
137#else 134#else
138#define cio_is_console(schid) 0 135#define cio_is_console(schid) 0
139#define cio_get_console_subchannel() NULL 136#define cio_get_console_subchannel() NULL
140#define cio_get_console_lock() NULL
141#define cio_get_console_priv() NULL
142#endif 137#endif
143 138
144#endif 139#endif
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 8a1294b1cbaf..fb0e64f1845a 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -139,19 +139,15 @@ static void css_sch_todo(struct work_struct *work);
139 139
140static void css_subchannel_release(struct device *dev) 140static void css_subchannel_release(struct device *dev)
141{ 141{
142 struct subchannel *sch; 142 struct subchannel *sch = to_subchannel(dev);
143 143
144 sch = to_subchannel(dev); 144 sch->config.intparm = 0;
145 if (!cio_is_console(sch->schid)) { 145 cio_commit_config(sch);
146 /* Reset intparm to zeroes. */ 146 kfree(sch->lock);
147 sch->config.intparm = 0; 147 kfree(sch);
148 cio_commit_config(sch);
149 kfree(sch->lock);
150 kfree(sch);
151 }
152} 148}
153 149
154static struct subchannel *css_alloc_subchannel(struct subchannel_id schid) 150struct subchannel *css_alloc_subchannel(struct subchannel_id schid)
155{ 151{
156 struct subchannel *sch; 152 struct subchannel *sch;
157 int ret; 153 int ret;
@@ -326,10 +322,9 @@ int css_probe_device(struct subchannel_id schid)
326 return PTR_ERR(sch); 322 return PTR_ERR(sch);
327 } 323 }
328 ret = css_register_subchannel(sch); 324 ret = css_register_subchannel(sch);
329 if (ret) { 325 if (ret)
330 if (!cio_is_console(schid)) 326 put_device(&sch->dev);
331 put_device(&sch->dev); 327
332 }
333 return ret; 328 return ret;
334} 329}
335 330
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 4af3dfe70ef5..6ab424d753a9 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -102,6 +102,7 @@ extern void css_driver_unregister(struct css_driver *);
102 102
103extern void css_sch_device_unregister(struct subchannel *); 103extern void css_sch_device_unregister(struct subchannel *);
104extern int css_probe_device(struct subchannel_id); 104extern int css_probe_device(struct subchannel_id);
105extern struct subchannel *css_alloc_subchannel(struct subchannel_id);
105extern struct subchannel *get_subchannel_by_schid(struct subchannel_id); 106extern struct subchannel *get_subchannel_by_schid(struct subchannel_id);
106extern int css_init_done; 107extern int css_init_done;
107extern int max_ssid; 108extern int max_ssid;
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 6ac0066d3158..25d04b7b5109 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1585,22 +1585,11 @@ static struct ccw_device console_cdev;
1585static struct ccw_device_private console_private; 1585static struct ccw_device_private console_private;
1586static int console_cdev_in_use; 1586static int console_cdev_in_use;
1587 1587
1588static DEFINE_SPINLOCK(ccw_console_lock);
1589
1590spinlock_t * cio_get_console_lock(void)
1591{
1592 return &ccw_console_lock;
1593}
1594
1595static int ccw_device_console_enable(struct ccw_device *cdev, 1588static int ccw_device_console_enable(struct ccw_device *cdev,
1596 struct subchannel *sch) 1589 struct subchannel *sch)
1597{ 1590{
1598 struct io_subchannel_private *io_priv = cio_get_console_priv();
1599 int rc; 1591 int rc;
1600 1592
1601 /* Attach subchannel private data. */
1602 memset(io_priv, 0, sizeof(*io_priv));
1603 set_io_private(sch, io_priv);
1604 io_subchannel_init_fields(sch); 1593 io_subchannel_init_fields(sch);
1605 rc = cio_commit_config(sch); 1594 rc = cio_commit_config(sch);
1606 if (rc) 1595 if (rc)
@@ -1633,6 +1622,7 @@ out_unlock:
1633struct ccw_device * 1622struct ccw_device *
1634ccw_device_probe_console(void) 1623ccw_device_probe_console(void)
1635{ 1624{
1625 struct io_subchannel_private *io_priv;
1636 struct subchannel *sch; 1626 struct subchannel *sch;
1637 int ret; 1627 int ret;
1638 1628
@@ -1648,10 +1638,20 @@ ccw_device_probe_console(void)
1648 console_cdev.private = &console_private; 1638 console_cdev.private = &console_private;
1649 console_private.cdev = &console_cdev; 1639 console_private.cdev = &console_cdev;
1650 console_private.int_class = IRQIO_CIO; 1640 console_private.int_class = IRQIO_CIO;
1641
1642 io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
1643 if (!io_priv) {
1644 put_device(&sch->dev);
1645 return ERR_PTR(-ENOMEM);
1646 }
1647 set_io_private(sch, io_priv);
1648
1651 ret = ccw_device_console_enable(&console_cdev, sch); 1649 ret = ccw_device_console_enable(&console_cdev, sch);
1652 if (ret) { 1650 if (ret) {
1653 cio_release_console();
1654 console_cdev_in_use = 0; 1651 console_cdev_in_use = 0;
1652 set_io_private(sch, NULL);
1653 put_device(&sch->dev);
1654 kfree(io_priv);
1655 return ERR_PTR(ret); 1655 return ERR_PTR(ret);
1656 } 1656 }
1657 console_cdev.online = 1; 1657 console_cdev.online = 1;