diff options
-rw-r--r-- | drivers/s390/cio/css.c | 36 | ||||
-rw-r--r-- | drivers/s390/cio/css.h | 4 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 50 |
3 files changed, 62 insertions, 28 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index e565193650c7..2d319fb812ca 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -542,9 +542,41 @@ css_bus_match (struct device *dev, struct device_driver *drv) | |||
542 | return 0; | 542 | return 0; |
543 | } | 543 | } |
544 | 544 | ||
545 | static int | ||
546 | css_probe (struct device *dev) | ||
547 | { | ||
548 | struct subchannel *sch; | ||
549 | |||
550 | sch = to_subchannel(dev); | ||
551 | sch->driver = container_of (dev->driver, struct css_driver, drv); | ||
552 | return (sch->driver->probe ? sch->driver->probe(sch) : 0); | ||
553 | } | ||
554 | |||
555 | static int | ||
556 | css_remove (struct device *dev) | ||
557 | { | ||
558 | struct subchannel *sch; | ||
559 | |||
560 | sch = to_subchannel(dev); | ||
561 | return (sch->driver->remove ? sch->driver->remove(sch) : 0); | ||
562 | } | ||
563 | |||
564 | static void | ||
565 | css_shutdown (struct device *dev) | ||
566 | { | ||
567 | struct subchannel *sch; | ||
568 | |||
569 | sch = to_subchannel(dev); | ||
570 | if (sch->driver->shutdown) | ||
571 | sch->driver->shutdown(sch); | ||
572 | } | ||
573 | |||
545 | struct bus_type css_bus_type = { | 574 | struct bus_type css_bus_type = { |
546 | .name = "css", | 575 | .name = "css", |
547 | .match = &css_bus_match, | 576 | .match = css_bus_match, |
577 | .probe = css_probe, | ||
578 | .remove = css_remove, | ||
579 | .shutdown = css_shutdown, | ||
548 | }; | 580 | }; |
549 | 581 | ||
550 | subsys_initcall(init_channel_subsystem); | 582 | subsys_initcall(init_channel_subsystem); |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 251ebd7a7d3a..aa5ab5d4547c 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -115,6 +115,7 @@ struct ccw_device_private { | |||
115 | * Currently, we only care about I/O subchannels (type 0), these | 115 | * Currently, we only care about I/O subchannels (type 0), these |
116 | * have a ccw_device connected to them. | 116 | * have a ccw_device connected to them. |
117 | */ | 117 | */ |
118 | struct subchannel; | ||
118 | struct css_driver { | 119 | struct css_driver { |
119 | unsigned int subchannel_type; | 120 | unsigned int subchannel_type; |
120 | struct device_driver drv; | 121 | struct device_driver drv; |
@@ -122,6 +123,9 @@ struct css_driver { | |||
122 | int (*notify)(struct device *, int); | 123 | int (*notify)(struct device *, int); |
123 | void (*verify)(struct device *); | 124 | void (*verify)(struct device *); |
124 | void (*termination)(struct device *); | 125 | void (*termination)(struct device *); |
126 | int (*probe)(struct subchannel *); | ||
127 | int (*remove)(struct subchannel *); | ||
128 | void (*shutdown)(struct subchannel *); | ||
125 | }; | 129 | }; |
126 | 130 | ||
127 | /* | 131 | /* |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index fa3e4c0a2536..eb73605a0527 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -107,33 +107,29 @@ ccw_uevent (struct device *dev, char **envp, int num_envp, | |||
107 | return 0; | 107 | return 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | struct bus_type ccw_bus_type = { | 110 | struct bus_type ccw_bus_type; |
111 | .name = "ccw", | ||
112 | .match = &ccw_bus_match, | ||
113 | .uevent = &ccw_uevent, | ||
114 | }; | ||
115 | 111 | ||
116 | static int io_subchannel_probe (struct device *); | 112 | static int io_subchannel_probe (struct subchannel *); |
117 | static int io_subchannel_remove (struct device *); | 113 | static int io_subchannel_remove (struct subchannel *); |
118 | void io_subchannel_irq (struct device *); | 114 | void io_subchannel_irq (struct device *); |
119 | static int io_subchannel_notify(struct device *, int); | 115 | static int io_subchannel_notify(struct device *, int); |
120 | static void io_subchannel_verify(struct device *); | 116 | static void io_subchannel_verify(struct device *); |
121 | static void io_subchannel_ioterm(struct device *); | 117 | static void io_subchannel_ioterm(struct device *); |
122 | static void io_subchannel_shutdown(struct device *); | 118 | static void io_subchannel_shutdown(struct subchannel *); |
123 | 119 | ||
124 | struct css_driver io_subchannel_driver = { | 120 | struct css_driver io_subchannel_driver = { |
125 | .subchannel_type = SUBCHANNEL_TYPE_IO, | 121 | .subchannel_type = SUBCHANNEL_TYPE_IO, |
126 | .drv = { | 122 | .drv = { |
127 | .name = "io_subchannel", | 123 | .name = "io_subchannel", |
128 | .bus = &css_bus_type, | 124 | .bus = &css_bus_type, |
129 | .probe = &io_subchannel_probe, | ||
130 | .remove = &io_subchannel_remove, | ||
131 | .shutdown = &io_subchannel_shutdown, | ||
132 | }, | 125 | }, |
133 | .irq = io_subchannel_irq, | 126 | .irq = io_subchannel_irq, |
134 | .notify = io_subchannel_notify, | 127 | .notify = io_subchannel_notify, |
135 | .verify = io_subchannel_verify, | 128 | .verify = io_subchannel_verify, |
136 | .termination = io_subchannel_ioterm, | 129 | .termination = io_subchannel_ioterm, |
130 | .probe = io_subchannel_probe, | ||
131 | .remove = io_subchannel_remove, | ||
132 | .shutdown = io_subchannel_shutdown, | ||
137 | }; | 133 | }; |
138 | 134 | ||
139 | struct workqueue_struct *ccw_device_work; | 135 | struct workqueue_struct *ccw_device_work; |
@@ -803,14 +799,12 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) | |||
803 | } | 799 | } |
804 | 800 | ||
805 | static int | 801 | static int |
806 | io_subchannel_probe (struct device *pdev) | 802 | io_subchannel_probe (struct subchannel *sch) |
807 | { | 803 | { |
808 | struct subchannel *sch; | ||
809 | struct ccw_device *cdev; | 804 | struct ccw_device *cdev; |
810 | int rc; | 805 | int rc; |
811 | unsigned long flags; | 806 | unsigned long flags; |
812 | 807 | ||
813 | sch = to_subchannel(pdev); | ||
814 | if (sch->dev.driver_data) { | 808 | if (sch->dev.driver_data) { |
815 | /* | 809 | /* |
816 | * This subchannel already has an associated ccw_device. | 810 | * This subchannel already has an associated ccw_device. |
@@ -846,7 +840,7 @@ io_subchannel_probe (struct device *pdev) | |||
846 | memset(cdev->private, 0, sizeof(struct ccw_device_private)); | 840 | memset(cdev->private, 0, sizeof(struct ccw_device_private)); |
847 | atomic_set(&cdev->private->onoff, 0); | 841 | atomic_set(&cdev->private->onoff, 0); |
848 | cdev->dev = (struct device) { | 842 | cdev->dev = (struct device) { |
849 | .parent = pdev, | 843 | .parent = &sch->dev, |
850 | .release = ccw_device_release, | 844 | .release = ccw_device_release, |
851 | }; | 845 | }; |
852 | INIT_LIST_HEAD(&cdev->private->kick_work.entry); | 846 | INIT_LIST_HEAD(&cdev->private->kick_work.entry); |
@@ -859,7 +853,7 @@ io_subchannel_probe (struct device *pdev) | |||
859 | return -ENODEV; | 853 | return -ENODEV; |
860 | } | 854 | } |
861 | 855 | ||
862 | rc = io_subchannel_recog(cdev, to_subchannel(pdev)); | 856 | rc = io_subchannel_recog(cdev, sch); |
863 | if (rc) { | 857 | if (rc) { |
864 | spin_lock_irqsave(&sch->lock, flags); | 858 | spin_lock_irqsave(&sch->lock, flags); |
865 | sch->dev.driver_data = NULL; | 859 | sch->dev.driver_data = NULL; |
@@ -883,17 +877,17 @@ ccw_device_unregister(void *data) | |||
883 | } | 877 | } |
884 | 878 | ||
885 | static int | 879 | static int |
886 | io_subchannel_remove (struct device *dev) | 880 | io_subchannel_remove (struct subchannel *sch) |
887 | { | 881 | { |
888 | struct ccw_device *cdev; | 882 | struct ccw_device *cdev; |
889 | unsigned long flags; | 883 | unsigned long flags; |
890 | 884 | ||
891 | if (!dev->driver_data) | 885 | if (!sch->dev.driver_data) |
892 | return 0; | 886 | return 0; |
893 | cdev = dev->driver_data; | 887 | cdev = sch->dev.driver_data; |
894 | /* Set ccw device to not operational and drop reference. */ | 888 | /* Set ccw device to not operational and drop reference. */ |
895 | spin_lock_irqsave(cdev->ccwlock, flags); | 889 | spin_lock_irqsave(cdev->ccwlock, flags); |
896 | dev->driver_data = NULL; | 890 | sch->dev.driver_data = NULL; |
897 | cdev->private->state = DEV_STATE_NOT_OPER; | 891 | cdev->private->state = DEV_STATE_NOT_OPER; |
898 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 892 | spin_unlock_irqrestore(cdev->ccwlock, flags); |
899 | /* | 893 | /* |
@@ -948,14 +942,12 @@ io_subchannel_ioterm(struct device *dev) | |||
948 | } | 942 | } |
949 | 943 | ||
950 | static void | 944 | static void |
951 | io_subchannel_shutdown(struct device *dev) | 945 | io_subchannel_shutdown(struct subchannel *sch) |
952 | { | 946 | { |
953 | struct subchannel *sch; | ||
954 | struct ccw_device *cdev; | 947 | struct ccw_device *cdev; |
955 | int ret; | 948 | int ret; |
956 | 949 | ||
957 | sch = to_subchannel(dev); | 950 | cdev = sch->dev.driver_data; |
958 | cdev = dev->driver_data; | ||
959 | 951 | ||
960 | if (cio_is_console(sch->schid)) | 952 | if (cio_is_console(sch->schid)) |
961 | return; | 953 | return; |
@@ -1129,6 +1121,14 @@ ccw_device_remove (struct device *dev) | |||
1129 | return 0; | 1121 | return 0; |
1130 | } | 1122 | } |
1131 | 1123 | ||
1124 | struct bus_type ccw_bus_type = { | ||
1125 | .name = "ccw", | ||
1126 | .match = ccw_bus_match, | ||
1127 | .uevent = ccw_uevent, | ||
1128 | .probe = ccw_device_probe, | ||
1129 | .remove = ccw_device_remove, | ||
1130 | }; | ||
1131 | |||
1132 | int | 1132 | int |
1133 | ccw_driver_register (struct ccw_driver *cdriver) | 1133 | ccw_driver_register (struct ccw_driver *cdriver) |
1134 | { | 1134 | { |
@@ -1136,8 +1136,6 @@ ccw_driver_register (struct ccw_driver *cdriver) | |||
1136 | 1136 | ||
1137 | drv->bus = &ccw_bus_type; | 1137 | drv->bus = &ccw_bus_type; |
1138 | drv->name = cdriver->name; | 1138 | drv->name = cdriver->name; |
1139 | drv->probe = ccw_device_probe; | ||
1140 | drv->remove = ccw_device_remove; | ||
1141 | 1139 | ||
1142 | return driver_register(drv); | 1140 | return driver_register(drv); |
1143 | } | 1141 | } |