diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-17 13:10:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-17 13:10:49 -0400 |
commit | 31598e8713ef501c8f6aad2e2ec8a9457e8877c1 (patch) | |
tree | 255d16a18cbfa78d15486eba07e03b222ddb5f77 /drivers/s390 | |
parent | 241eb95600be194f6b59b85c0bf41194694ebdf1 (diff) | |
parent | 6966727db1389f4926c6fa6e87a600112a5658b9 (diff) |
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6:
[S390] kexec: Disable ftrace during kexec
[S390] support XZ compressed kernel
[S390] css_bus_type: make it static
[S390] css_driver: remove duplicate members
[S390] css: remove subchannel private
[S390] css: move chsc_private to drv_data
[S390] css: move io_private to drv_data
[S390] cio: move cdev pointer to io_subchannel_private
[S390] cio: move options to io_sch_private
[S390] cio: move asms to generic header
[S390] cio: move orb definitions to separate header
[S390] Write protect module text and RO data
[S390] dasd: get rid of compile warning
[S390] remove superfluous check from do_IRQ
[S390] remove redundant stack check option
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 1 | ||||
-rw-r--r-- | drivers/s390/cio/chsc_sch.c | 17 | ||||
-rw-r--r-- | drivers/s390/cio/cio.c | 43 | ||||
-rw-r--r-- | drivers/s390/cio/cio.h | 11 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 6 | ||||
-rw-r--r-- | drivers/s390/cio/css.h | 10 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 23 | ||||
-rw-r--r-- | drivers/s390/cio/io_sch.h | 114 | ||||
-rw-r--r-- | drivers/s390/cio/ioasm.h | 34 | ||||
-rw-r--r-- | drivers/s390/cio/orb.h | 67 |
10 files changed, 166 insertions, 160 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index a9fe23d5bd0f..379d8592bc6e 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -2648,6 +2648,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
2648 | dasd_sfree_request(cqr, startdev); | 2648 | dasd_sfree_request(cqr, startdev); |
2649 | return ERR_PTR(-EAGAIN); | 2649 | return ERR_PTR(-EAGAIN); |
2650 | } | 2650 | } |
2651 | len_to_track_end = 0; | ||
2651 | /* | 2652 | /* |
2652 | * A tidaw can address 4k of memory, but must not cross page boundaries | 2653 | * A tidaw can address 4k of memory, but must not cross page boundaries |
2653 | * We can let the block layer handle this by setting | 2654 | * We can let the block layer handle this by setting |
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 3c3f3ffe2179..e950f1ad4dd1 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c | |||
@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL"); | |||
50 | 50 | ||
51 | static void chsc_subchannel_irq(struct subchannel *sch) | 51 | static void chsc_subchannel_irq(struct subchannel *sch) |
52 | { | 52 | { |
53 | struct chsc_private *private = sch->private; | 53 | struct chsc_private *private = dev_get_drvdata(&sch->dev); |
54 | struct chsc_request *request = private->request; | 54 | struct chsc_request *request = private->request; |
55 | struct irb *irb = (struct irb *)&S390_lowcore.irb; | 55 | struct irb *irb = (struct irb *)&S390_lowcore.irb; |
56 | 56 | ||
@@ -80,13 +80,14 @@ static int chsc_subchannel_probe(struct subchannel *sch) | |||
80 | private = kzalloc(sizeof(*private), GFP_KERNEL); | 80 | private = kzalloc(sizeof(*private), GFP_KERNEL); |
81 | if (!private) | 81 | if (!private) |
82 | return -ENOMEM; | 82 | return -ENOMEM; |
83 | dev_set_drvdata(&sch->dev, private); | ||
83 | ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch); | 84 | ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch); |
84 | if (ret) { | 85 | if (ret) { |
85 | CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n", | 86 | CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n", |
86 | sch->schid.ssid, sch->schid.sch_no, ret); | 87 | sch->schid.ssid, sch->schid.sch_no, ret); |
88 | dev_set_drvdata(&sch->dev, NULL); | ||
87 | kfree(private); | 89 | kfree(private); |
88 | } else { | 90 | } else { |
89 | sch->private = private; | ||
90 | if (dev_get_uevent_suppress(&sch->dev)) { | 91 | if (dev_get_uevent_suppress(&sch->dev)) { |
91 | dev_set_uevent_suppress(&sch->dev, 0); | 92 | dev_set_uevent_suppress(&sch->dev, 0); |
92 | kobject_uevent(&sch->dev.kobj, KOBJ_ADD); | 93 | kobject_uevent(&sch->dev.kobj, KOBJ_ADD); |
@@ -100,8 +101,8 @@ static int chsc_subchannel_remove(struct subchannel *sch) | |||
100 | struct chsc_private *private; | 101 | struct chsc_private *private; |
101 | 102 | ||
102 | cio_disable_subchannel(sch); | 103 | cio_disable_subchannel(sch); |
103 | private = sch->private; | 104 | private = dev_get_drvdata(&sch->dev); |
104 | sch->private = NULL; | 105 | dev_set_drvdata(&sch->dev, NULL); |
105 | if (private->request) { | 106 | if (private->request) { |
106 | complete(&private->request->completion); | 107 | complete(&private->request->completion); |
107 | put_device(&sch->dev); | 108 | put_device(&sch->dev); |
@@ -147,7 +148,10 @@ static struct css_device_id chsc_subchannel_ids[] = { | |||
147 | MODULE_DEVICE_TABLE(css, chsc_subchannel_ids); | 148 | MODULE_DEVICE_TABLE(css, chsc_subchannel_ids); |
148 | 149 | ||
149 | static struct css_driver chsc_subchannel_driver = { | 150 | static struct css_driver chsc_subchannel_driver = { |
150 | .owner = THIS_MODULE, | 151 | .drv = { |
152 | .owner = THIS_MODULE, | ||
153 | .name = "chsc_subchannel", | ||
154 | }, | ||
151 | .subchannel_type = chsc_subchannel_ids, | 155 | .subchannel_type = chsc_subchannel_ids, |
152 | .irq = chsc_subchannel_irq, | 156 | .irq = chsc_subchannel_irq, |
153 | .probe = chsc_subchannel_probe, | 157 | .probe = chsc_subchannel_probe, |
@@ -157,7 +161,6 @@ static struct css_driver chsc_subchannel_driver = { | |||
157 | .freeze = chsc_subchannel_freeze, | 161 | .freeze = chsc_subchannel_freeze, |
158 | .thaw = chsc_subchannel_restore, | 162 | .thaw = chsc_subchannel_restore, |
159 | .restore = chsc_subchannel_restore, | 163 | .restore = chsc_subchannel_restore, |
160 | .name = "chsc_subchannel", | ||
161 | }; | 164 | }; |
162 | 165 | ||
163 | static int __init chsc_init_dbfs(void) | 166 | static int __init chsc_init_dbfs(void) |
@@ -241,7 +244,7 @@ static int chsc_async(struct chsc_async_area *chsc_area, | |||
241 | chsc_area->header.key = PAGE_DEFAULT_KEY >> 4; | 244 | chsc_area->header.key = PAGE_DEFAULT_KEY >> 4; |
242 | while ((sch = chsc_get_next_subchannel(sch))) { | 245 | while ((sch = chsc_get_next_subchannel(sch))) { |
243 | spin_lock(sch->lock); | 246 | spin_lock(sch->lock); |
244 | private = sch->private; | 247 | private = dev_get_drvdata(&sch->dev); |
245 | if (private->request) { | 248 | if (private->request) { |
246 | spin_unlock(sch->lock); | 249 | spin_unlock(sch->lock); |
247 | ret = -EBUSY; | 250 | ret = -EBUSY; |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 430f875006f2..cbde448f9947 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -84,29 +84,14 @@ out_unregister: | |||
84 | 84 | ||
85 | arch_initcall (cio_debug_init); | 85 | arch_initcall (cio_debug_init); |
86 | 86 | ||
87 | int | 87 | int cio_set_options(struct subchannel *sch, int flags) |
88 | cio_set_options (struct subchannel *sch, int flags) | ||
89 | { | 88 | { |
90 | sch->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0; | 89 | struct io_subchannel_private *priv = to_io_private(sch); |
91 | sch->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0; | ||
92 | sch->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0; | ||
93 | return 0; | ||
94 | } | ||
95 | 90 | ||
96 | /* FIXME: who wants to use this? */ | 91 | priv->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0; |
97 | int | 92 | priv->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0; |
98 | cio_get_options (struct subchannel *sch) | 93 | priv->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0; |
99 | { | 94 | return 0; |
100 | int flags; | ||
101 | |||
102 | flags = 0; | ||
103 | if (sch->options.suspend) | ||
104 | flags |= DOIO_ALLOW_SUSPEND; | ||
105 | if (sch->options.prefetch) | ||
106 | flags |= DOIO_DENY_PREFETCH; | ||
107 | if (sch->options.inter) | ||
108 | flags |= DOIO_SUPPRESS_INTER; | ||
109 | return flags; | ||
110 | } | 95 | } |
111 | 96 | ||
112 | static int | 97 | static int |
@@ -139,21 +124,21 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ | |||
139 | __u8 lpm, /* logical path mask */ | 124 | __u8 lpm, /* logical path mask */ |
140 | __u8 key) /* storage key */ | 125 | __u8 key) /* storage key */ |
141 | { | 126 | { |
127 | struct io_subchannel_private *priv = to_io_private(sch); | ||
128 | union orb *orb = &priv->orb; | ||
142 | int ccode; | 129 | int ccode; |
143 | union orb *orb; | ||
144 | 130 | ||
145 | CIO_TRACE_EVENT(5, "stIO"); | 131 | CIO_TRACE_EVENT(5, "stIO"); |
146 | CIO_TRACE_EVENT(5, dev_name(&sch->dev)); | 132 | CIO_TRACE_EVENT(5, dev_name(&sch->dev)); |
147 | 133 | ||
148 | orb = &to_io_private(sch)->orb; | ||
149 | memset(orb, 0, sizeof(union orb)); | 134 | memset(orb, 0, sizeof(union orb)); |
150 | /* sch is always under 2G. */ | 135 | /* sch is always under 2G. */ |
151 | orb->cmd.intparm = (u32)(addr_t)sch; | 136 | orb->cmd.intparm = (u32)(addr_t)sch; |
152 | orb->cmd.fmt = 1; | 137 | orb->cmd.fmt = 1; |
153 | 138 | ||
154 | orb->cmd.pfch = sch->options.prefetch == 0; | 139 | orb->cmd.pfch = priv->options.prefetch == 0; |
155 | orb->cmd.spnd = sch->options.suspend; | 140 | orb->cmd.spnd = priv->options.suspend; |
156 | orb->cmd.ssic = sch->options.suspend && sch->options.inter; | 141 | orb->cmd.ssic = priv->options.suspend && priv->options.inter; |
157 | orb->cmd.lpm = (lpm != 0) ? lpm : sch->lpm; | 142 | orb->cmd.lpm = (lpm != 0) ? lpm : sch->lpm; |
158 | #ifdef CONFIG_64BIT | 143 | #ifdef CONFIG_64BIT |
159 | /* | 144 | /* |
@@ -630,11 +615,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
630 | irb = (struct irb *)&S390_lowcore.irb; | 615 | irb = (struct irb *)&S390_lowcore.irb; |
631 | do { | 616 | do { |
632 | kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; | 617 | kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; |
633 | /* | 618 | if (tpi_info->adapter_IO) { |
634 | * Non I/O-subchannel thin interrupts are processed differently | ||
635 | */ | ||
636 | if (tpi_info->adapter_IO == 1 && | ||
637 | tpi_info->int_type == IO_INTERRUPT_TYPE) { | ||
638 | do_adapter_IO(tpi_info->isc); | 619 | do_adapter_IO(tpi_info->isc); |
639 | continue; | 620 | continue; |
640 | } | 621 | } |
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index bf7f80f5a330..155a82bcb9e5 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h | |||
@@ -84,13 +84,6 @@ struct subchannel { | |||
84 | SUBCHANNEL_TYPE_MSG = 2, | 84 | SUBCHANNEL_TYPE_MSG = 2, |
85 | SUBCHANNEL_TYPE_ADM = 3, | 85 | SUBCHANNEL_TYPE_ADM = 3, |
86 | } st; /* subchannel type */ | 86 | } st; /* subchannel type */ |
87 | |||
88 | struct { | ||
89 | unsigned int suspend:1; /* allow suspend */ | ||
90 | unsigned int prefetch:1;/* deny prefetch */ | ||
91 | unsigned int inter:1; /* suppress intermediate interrupts */ | ||
92 | } __attribute__ ((packed)) options; | ||
93 | |||
94 | __u8 vpm; /* verified path mask */ | 87 | __u8 vpm; /* verified path mask */ |
95 | __u8 lpm; /* logical path mask */ | 88 | __u8 lpm; /* logical path mask */ |
96 | __u8 opm; /* operational path mask */ | 89 | __u8 opm; /* operational path mask */ |
@@ -99,14 +92,11 @@ struct subchannel { | |||
99 | struct chsc_ssd_info ssd_info; /* subchannel description */ | 92 | struct chsc_ssd_info ssd_info; /* subchannel description */ |
100 | struct device dev; /* entry in device tree */ | 93 | struct device dev; /* entry in device tree */ |
101 | struct css_driver *driver; | 94 | struct css_driver *driver; |
102 | void *private; /* private per subchannel type data */ | ||
103 | enum sch_todo todo; | 95 | enum sch_todo todo; |
104 | struct work_struct todo_work; | 96 | struct work_struct todo_work; |
105 | struct schib_config config; | 97 | struct schib_config config; |
106 | } __attribute__ ((aligned(8))); | 98 | } __attribute__ ((aligned(8))); |
107 | 99 | ||
108 | #define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */ | ||
109 | |||
110 | #define to_subchannel(n) container_of(n, struct subchannel, dev) | 100 | #define to_subchannel(n) container_of(n, struct subchannel, dev) |
111 | 101 | ||
112 | extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); | 102 | extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); |
@@ -120,7 +110,6 @@ extern int cio_start (struct subchannel *, struct ccw1 *, __u8); | |||
120 | extern int cio_start_key (struct subchannel *, struct ccw1 *, __u8, __u8); | 110 | extern int cio_start_key (struct subchannel *, struct ccw1 *, __u8, __u8); |
121 | extern int cio_cancel (struct subchannel *); | 111 | extern int cio_cancel (struct subchannel *); |
122 | extern int cio_set_options (struct subchannel *, int); | 112 | extern int cio_set_options (struct subchannel *, int); |
123 | extern int cio_get_options (struct subchannel *); | ||
124 | extern int cio_update_schib(struct subchannel *sch); | 113 | extern int cio_update_schib(struct subchannel *sch); |
125 | extern int cio_commit_config(struct subchannel *sch); | 114 | extern int cio_commit_config(struct subchannel *sch); |
126 | 115 | ||
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 24d8e97355b9..c47b25fd3f43 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -35,6 +35,7 @@ int css_init_done = 0; | |||
35 | int max_ssid; | 35 | int max_ssid; |
36 | 36 | ||
37 | struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; | 37 | struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; |
38 | static struct bus_type css_bus_type; | ||
38 | 39 | ||
39 | int | 40 | int |
40 | for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) | 41 | for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) |
@@ -1214,7 +1215,7 @@ static const struct dev_pm_ops css_pm_ops = { | |||
1214 | .restore = css_pm_restore, | 1215 | .restore = css_pm_restore, |
1215 | }; | 1216 | }; |
1216 | 1217 | ||
1217 | struct bus_type css_bus_type = { | 1218 | static struct bus_type css_bus_type = { |
1218 | .name = "css", | 1219 | .name = "css", |
1219 | .match = css_bus_match, | 1220 | .match = css_bus_match, |
1220 | .probe = css_probe, | 1221 | .probe = css_probe, |
@@ -1233,9 +1234,7 @@ struct bus_type css_bus_type = { | |||
1233 | */ | 1234 | */ |
1234 | int css_driver_register(struct css_driver *cdrv) | 1235 | int css_driver_register(struct css_driver *cdrv) |
1235 | { | 1236 | { |
1236 | cdrv->drv.name = cdrv->name; | ||
1237 | cdrv->drv.bus = &css_bus_type; | 1237 | cdrv->drv.bus = &css_bus_type; |
1238 | cdrv->drv.owner = cdrv->owner; | ||
1239 | return driver_register(&cdrv->drv); | 1238 | return driver_register(&cdrv->drv); |
1240 | } | 1239 | } |
1241 | EXPORT_SYMBOL_GPL(css_driver_register); | 1240 | EXPORT_SYMBOL_GPL(css_driver_register); |
@@ -1253,4 +1252,3 @@ void css_driver_unregister(struct css_driver *cdrv) | |||
1253 | EXPORT_SYMBOL_GPL(css_driver_unregister); | 1252 | EXPORT_SYMBOL_GPL(css_driver_unregister); |
1254 | 1253 | ||
1255 | MODULE_LICENSE("GPL"); | 1254 | MODULE_LICENSE("GPL"); |
1256 | EXPORT_SYMBOL(css_bus_type); | ||
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 7e37886de231..80ebdddf7747 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -63,7 +63,6 @@ struct subchannel; | |||
63 | struct chp_link; | 63 | struct chp_link; |
64 | /** | 64 | /** |
65 | * struct css_driver - device driver for subchannels | 65 | * struct css_driver - device driver for subchannels |
66 | * @owner: owning module | ||
67 | * @subchannel_type: subchannel type supported by this driver | 66 | * @subchannel_type: subchannel type supported by this driver |
68 | * @drv: embedded device driver structure | 67 | * @drv: embedded device driver structure |
69 | * @irq: called on interrupts | 68 | * @irq: called on interrupts |
@@ -78,10 +77,8 @@ struct chp_link; | |||
78 | * @thaw: undo work done in @freeze | 77 | * @thaw: undo work done in @freeze |
79 | * @restore: callback for restoring after hibernation | 78 | * @restore: callback for restoring after hibernation |
80 | * @settle: wait for asynchronous work to finish | 79 | * @settle: wait for asynchronous work to finish |
81 | * @name: name of the device driver | ||
82 | */ | 80 | */ |
83 | struct css_driver { | 81 | struct css_driver { |
84 | struct module *owner; | ||
85 | struct css_device_id *subchannel_type; | 82 | struct css_device_id *subchannel_type; |
86 | struct device_driver drv; | 83 | struct device_driver drv; |
87 | void (*irq)(struct subchannel *); | 84 | void (*irq)(struct subchannel *); |
@@ -96,16 +93,10 @@ struct css_driver { | |||
96 | int (*thaw) (struct subchannel *); | 93 | int (*thaw) (struct subchannel *); |
97 | int (*restore)(struct subchannel *); | 94 | int (*restore)(struct subchannel *); |
98 | int (*settle)(void); | 95 | int (*settle)(void); |
99 | const char *name; | ||
100 | }; | 96 | }; |
101 | 97 | ||
102 | #define to_cssdriver(n) container_of(n, struct css_driver, drv) | 98 | #define to_cssdriver(n) container_of(n, struct css_driver, drv) |
103 | 99 | ||
104 | /* | ||
105 | * all css_drivers have the css_bus_type | ||
106 | */ | ||
107 | extern struct bus_type css_bus_type; | ||
108 | |||
109 | extern int css_driver_register(struct css_driver *); | 100 | extern int css_driver_register(struct css_driver *); |
110 | extern void css_driver_unregister(struct css_driver *); | 101 | extern void css_driver_unregister(struct css_driver *); |
111 | 102 | ||
@@ -140,7 +131,6 @@ struct channel_subsystem { | |||
140 | }; | 131 | }; |
141 | #define to_css(dev) container_of(dev, struct channel_subsystem, device) | 132 | #define to_css(dev) container_of(dev, struct channel_subsystem, device) |
142 | 133 | ||
143 | extern struct bus_type css_bus_type; | ||
144 | extern struct channel_subsystem *channel_subsystems[]; | 134 | extern struct channel_subsystem *channel_subsystems[]; |
145 | 135 | ||
146 | /* Helper functions to build lists for the slow path. */ | 136 | /* Helper functions to build lists for the slow path. */ |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index b7eaff9ca19e..e50b12163afe 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -172,9 +172,11 @@ static int io_subchannel_settle(void) | |||
172 | } | 172 | } |
173 | 173 | ||
174 | static struct css_driver io_subchannel_driver = { | 174 | static struct css_driver io_subchannel_driver = { |
175 | .owner = THIS_MODULE, | 175 | .drv = { |
176 | .owner = THIS_MODULE, | ||
177 | .name = "io_subchannel", | ||
178 | }, | ||
176 | .subchannel_type = io_subchannel_ids, | 179 | .subchannel_type = io_subchannel_ids, |
177 | .name = "io_subchannel", | ||
178 | .irq = io_subchannel_irq, | 180 | .irq = io_subchannel_irq, |
179 | .sch_event = io_subchannel_sch_event, | 181 | .sch_event = io_subchannel_sch_event, |
180 | .chp_event = io_subchannel_chp_event, | 182 | .chp_event = io_subchannel_chp_event, |
@@ -1030,6 +1032,7 @@ static void io_subchannel_init_fields(struct subchannel *sch) | |||
1030 | */ | 1032 | */ |
1031 | static int io_subchannel_probe(struct subchannel *sch) | 1033 | static int io_subchannel_probe(struct subchannel *sch) |
1032 | { | 1034 | { |
1035 | struct io_subchannel_private *io_priv; | ||
1033 | struct ccw_device *cdev; | 1036 | struct ccw_device *cdev; |
1034 | int rc; | 1037 | int rc; |
1035 | 1038 | ||
@@ -1073,10 +1076,11 @@ static int io_subchannel_probe(struct subchannel *sch) | |||
1073 | if (rc) | 1076 | if (rc) |
1074 | goto out_schedule; | 1077 | goto out_schedule; |
1075 | /* Allocate I/O subchannel private data. */ | 1078 | /* Allocate I/O subchannel private data. */ |
1076 | sch->private = kzalloc(sizeof(struct io_subchannel_private), | 1079 | io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA); |
1077 | GFP_KERNEL | GFP_DMA); | 1080 | if (!io_priv) |
1078 | if (!sch->private) | ||
1079 | goto out_schedule; | 1081 | goto out_schedule; |
1082 | |||
1083 | set_io_private(sch, io_priv); | ||
1080 | css_schedule_eval(sch->schid); | 1084 | css_schedule_eval(sch->schid); |
1081 | return 0; | 1085 | return 0; |
1082 | 1086 | ||
@@ -1090,6 +1094,7 @@ out_schedule: | |||
1090 | static int | 1094 | static int |
1091 | io_subchannel_remove (struct subchannel *sch) | 1095 | io_subchannel_remove (struct subchannel *sch) |
1092 | { | 1096 | { |
1097 | struct io_subchannel_private *io_priv = to_io_private(sch); | ||
1093 | struct ccw_device *cdev; | 1098 | struct ccw_device *cdev; |
1094 | 1099 | ||
1095 | cdev = sch_get_cdev(sch); | 1100 | cdev = sch_get_cdev(sch); |
@@ -1099,11 +1104,12 @@ io_subchannel_remove (struct subchannel *sch) | |||
1099 | /* Set ccw device to not operational and drop reference. */ | 1104 | /* Set ccw device to not operational and drop reference. */ |
1100 | spin_lock_irq(cdev->ccwlock); | 1105 | spin_lock_irq(cdev->ccwlock); |
1101 | sch_set_cdev(sch, NULL); | 1106 | sch_set_cdev(sch, NULL); |
1107 | set_io_private(sch, NULL); | ||
1102 | cdev->private->state = DEV_STATE_NOT_OPER; | 1108 | cdev->private->state = DEV_STATE_NOT_OPER; |
1103 | spin_unlock_irq(cdev->ccwlock); | 1109 | spin_unlock_irq(cdev->ccwlock); |
1104 | ccw_device_unregister(cdev); | 1110 | ccw_device_unregister(cdev); |
1105 | out_free: | 1111 | out_free: |
1106 | kfree(sch->private); | 1112 | kfree(io_priv); |
1107 | sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); | 1113 | sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); |
1108 | return 0; | 1114 | return 0; |
1109 | } | 1115 | } |
@@ -1553,11 +1559,12 @@ spinlock_t * cio_get_console_lock(void) | |||
1553 | static int ccw_device_console_enable(struct ccw_device *cdev, | 1559 | static int ccw_device_console_enable(struct ccw_device *cdev, |
1554 | struct subchannel *sch) | 1560 | struct subchannel *sch) |
1555 | { | 1561 | { |
1562 | struct io_subchannel_private *io_priv = cio_get_console_priv(); | ||
1556 | int rc; | 1563 | int rc; |
1557 | 1564 | ||
1558 | /* Attach subchannel private data. */ | 1565 | /* Attach subchannel private data. */ |
1559 | sch->private = cio_get_console_priv(); | 1566 | memset(io_priv, 0, sizeof(*io_priv)); |
1560 | memset(sch->private, 0, sizeof(struct io_subchannel_private)); | 1567 | set_io_private(sch, io_priv); |
1561 | io_subchannel_init_fields(sch); | 1568 | io_subchannel_init_fields(sch); |
1562 | rc = cio_commit_config(sch); | 1569 | rc = cio_commit_config(sch); |
1563 | if (rc) | 1570 | if (rc) |
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h index d024d2c21897..ba31ad88f4f7 100644 --- a/drivers/s390/cio/io_sch.h +++ b/drivers/s390/cio/io_sch.h | |||
@@ -5,68 +5,36 @@ | |||
5 | #include <asm/schid.h> | 5 | #include <asm/schid.h> |
6 | #include <asm/ccwdev.h> | 6 | #include <asm/ccwdev.h> |
7 | #include "css.h" | 7 | #include "css.h" |
8 | 8 | #include "orb.h" | |
9 | /* | ||
10 | * command-mode operation request block | ||
11 | */ | ||
12 | struct cmd_orb { | ||
13 | u32 intparm; /* interruption parameter */ | ||
14 | u32 key : 4; /* flags, like key, suspend control, etc. */ | ||
15 | u32 spnd : 1; /* suspend control */ | ||
16 | u32 res1 : 1; /* reserved */ | ||
17 | u32 mod : 1; /* modification control */ | ||
18 | u32 sync : 1; /* synchronize control */ | ||
19 | u32 fmt : 1; /* format control */ | ||
20 | u32 pfch : 1; /* prefetch control */ | ||
21 | u32 isic : 1; /* initial-status-interruption control */ | ||
22 | u32 alcc : 1; /* address-limit-checking control */ | ||
23 | u32 ssic : 1; /* suppress-suspended-interr. control */ | ||
24 | u32 res2 : 1; /* reserved */ | ||
25 | u32 c64 : 1; /* IDAW/QDIO 64 bit control */ | ||
26 | u32 i2k : 1; /* IDAW 2/4kB block size control */ | ||
27 | u32 lpm : 8; /* logical path mask */ | ||
28 | u32 ils : 1; /* incorrect length */ | ||
29 | u32 zero : 6; /* reserved zeros */ | ||
30 | u32 orbx : 1; /* ORB extension control */ | ||
31 | u32 cpa; /* channel program address */ | ||
32 | } __attribute__ ((packed, aligned(4))); | ||
33 | |||
34 | /* | ||
35 | * transport-mode operation request block | ||
36 | */ | ||
37 | struct tm_orb { | ||
38 | u32 intparm; | ||
39 | u32 key:4; | ||
40 | u32 :9; | ||
41 | u32 b:1; | ||
42 | u32 :2; | ||
43 | u32 lpm:8; | ||
44 | u32 :7; | ||
45 | u32 x:1; | ||
46 | u32 tcw; | ||
47 | u32 prio:8; | ||
48 | u32 :8; | ||
49 | u32 rsvpgm:8; | ||
50 | u32 :8; | ||
51 | u32 :32; | ||
52 | u32 :32; | ||
53 | u32 :32; | ||
54 | u32 :32; | ||
55 | } __attribute__ ((packed, aligned(4))); | ||
56 | |||
57 | union orb { | ||
58 | struct cmd_orb cmd; | ||
59 | struct tm_orb tm; | ||
60 | } __attribute__ ((packed, aligned(4))); | ||
61 | 9 | ||
62 | struct io_subchannel_private { | 10 | struct io_subchannel_private { |
63 | union orb orb; /* operation request block */ | 11 | union orb orb; /* operation request block */ |
64 | struct ccw1 sense_ccw; /* static ccw for sense command */ | 12 | struct ccw1 sense_ccw; /* static ccw for sense command */ |
65 | } __attribute__ ((aligned(8))); | 13 | struct ccw_device *cdev;/* pointer to the child ccw device */ |
14 | struct { | ||
15 | unsigned int suspend:1; /* allow suspend */ | ||
16 | unsigned int prefetch:1;/* deny prefetch */ | ||
17 | unsigned int inter:1; /* suppress intermediate interrupts */ | ||
18 | } __packed options; | ||
19 | } __aligned(8); | ||
66 | 20 | ||
67 | #define to_io_private(n) ((struct io_subchannel_private *)n->private) | 21 | #define to_io_private(n) ((struct io_subchannel_private *) \ |
68 | #define sch_get_cdev(n) (dev_get_drvdata(&n->dev)) | 22 | dev_get_drvdata(&(n)->dev)) |
69 | #define sch_set_cdev(n, c) (dev_set_drvdata(&n->dev, c)) | 23 | #define set_io_private(n, p) (dev_set_drvdata(&(n)->dev, p)) |
24 | |||
25 | static inline struct ccw_device *sch_get_cdev(struct subchannel *sch) | ||
26 | { | ||
27 | struct io_subchannel_private *priv = to_io_private(sch); | ||
28 | return priv ? priv->cdev : NULL; | ||
29 | } | ||
30 | |||
31 | static inline void sch_set_cdev(struct subchannel *sch, | ||
32 | struct ccw_device *cdev) | ||
33 | { | ||
34 | struct io_subchannel_private *priv = to_io_private(sch); | ||
35 | if (priv) | ||
36 | priv->cdev = cdev; | ||
37 | } | ||
70 | 38 | ||
71 | #define MAX_CIWS 8 | 39 | #define MAX_CIWS 8 |
72 | 40 | ||
@@ -191,23 +159,6 @@ struct ccw_device_private { | |||
191 | void *cmb_wait; /* deferred cmb enable/disable */ | 159 | void *cmb_wait; /* deferred cmb enable/disable */ |
192 | }; | 160 | }; |
193 | 161 | ||
194 | static inline int ssch(struct subchannel_id schid, union orb *addr) | ||
195 | { | ||
196 | register struct subchannel_id reg1 asm("1") = schid; | ||
197 | int ccode = -EIO; | ||
198 | |||
199 | asm volatile( | ||
200 | " ssch 0(%2)\n" | ||
201 | "0: ipm %0\n" | ||
202 | " srl %0,28\n" | ||
203 | "1:\n" | ||
204 | EX_TABLE(0b, 1b) | ||
205 | : "+d" (ccode) | ||
206 | : "d" (reg1), "a" (addr), "m" (*addr) | ||
207 | : "cc", "memory"); | ||
208 | return ccode; | ||
209 | } | ||
210 | |||
211 | static inline int rsch(struct subchannel_id schid) | 162 | static inline int rsch(struct subchannel_id schid) |
212 | { | 163 | { |
213 | register struct subchannel_id reg1 asm("1") = schid; | 164 | register struct subchannel_id reg1 asm("1") = schid; |
@@ -223,21 +174,6 @@ static inline int rsch(struct subchannel_id schid) | |||
223 | return ccode; | 174 | return ccode; |
224 | } | 175 | } |
225 | 176 | ||
226 | static inline int csch(struct subchannel_id schid) | ||
227 | { | ||
228 | register struct subchannel_id reg1 asm("1") = schid; | ||
229 | int ccode; | ||
230 | |||
231 | asm volatile( | ||
232 | " csch\n" | ||
233 | " ipm %0\n" | ||
234 | " srl %0,28" | ||
235 | : "=d" (ccode) | ||
236 | : "d" (reg1) | ||
237 | : "cc"); | ||
238 | return ccode; | ||
239 | } | ||
240 | |||
241 | static inline int hsch(struct subchannel_id schid) | 177 | static inline int hsch(struct subchannel_id schid) |
242 | { | 178 | { |
243 | register struct subchannel_id reg1 asm("1") = schid; | 179 | register struct subchannel_id reg1 asm("1") = schid; |
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index fac06155773f..4d80fc67a06b 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | #include <asm/chpid.h> | 4 | #include <asm/chpid.h> |
5 | #include <asm/schid.h> | 5 | #include <asm/schid.h> |
6 | #include "orb.h" | ||
7 | #include "cio.h" | ||
6 | 8 | ||
7 | /* | 9 | /* |
8 | * TPI info structure | 10 | * TPI info structure |
@@ -87,6 +89,38 @@ static inline int tsch(struct subchannel_id schid, struct irb *addr) | |||
87 | return ccode; | 89 | return ccode; |
88 | } | 90 | } |
89 | 91 | ||
92 | static inline int ssch(struct subchannel_id schid, union orb *addr) | ||
93 | { | ||
94 | register struct subchannel_id reg1 asm("1") = schid; | ||
95 | int ccode = -EIO; | ||
96 | |||
97 | asm volatile( | ||
98 | " ssch 0(%2)\n" | ||
99 | "0: ipm %0\n" | ||
100 | " srl %0,28\n" | ||
101 | "1:\n" | ||
102 | EX_TABLE(0b, 1b) | ||
103 | : "+d" (ccode) | ||
104 | : "d" (reg1), "a" (addr), "m" (*addr) | ||
105 | : "cc", "memory"); | ||
106 | return ccode; | ||
107 | } | ||
108 | |||
109 | static inline int csch(struct subchannel_id schid) | ||
110 | { | ||
111 | register struct subchannel_id reg1 asm("1") = schid; | ||
112 | int ccode; | ||
113 | |||
114 | asm volatile( | ||
115 | " csch\n" | ||
116 | " ipm %0\n" | ||
117 | " srl %0,28" | ||
118 | : "=d" (ccode) | ||
119 | : "d" (reg1) | ||
120 | : "cc"); | ||
121 | return ccode; | ||
122 | } | ||
123 | |||
90 | static inline int tpi(struct tpi_info *addr) | 124 | static inline int tpi(struct tpi_info *addr) |
91 | { | 125 | { |
92 | int ccode; | 126 | int ccode; |
diff --git a/drivers/s390/cio/orb.h b/drivers/s390/cio/orb.h new file mode 100644 index 000000000000..45a9865c2b36 --- /dev/null +++ b/drivers/s390/cio/orb.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Orb related data structures. | ||
3 | * | ||
4 | * Copyright IBM Corp. 2007, 2011 | ||
5 | * | ||
6 | * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> | ||
7 | * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> | ||
8 | * Sebastian Ott <sebott@linux.vnet.ibm.com> | ||
9 | */ | ||
10 | |||
11 | #ifndef S390_ORB_H | ||
12 | #define S390_ORB_H | ||
13 | |||
14 | /* | ||
15 | * Command-mode operation request block | ||
16 | */ | ||
17 | struct cmd_orb { | ||
18 | u32 intparm; /* interruption parameter */ | ||
19 | u32 key:4; /* flags, like key, suspend control, etc. */ | ||
20 | u32 spnd:1; /* suspend control */ | ||
21 | u32 res1:1; /* reserved */ | ||
22 | u32 mod:1; /* modification control */ | ||
23 | u32 sync:1; /* synchronize control */ | ||
24 | u32 fmt:1; /* format control */ | ||
25 | u32 pfch:1; /* prefetch control */ | ||
26 | u32 isic:1; /* initial-status-interruption control */ | ||
27 | u32 alcc:1; /* address-limit-checking control */ | ||
28 | u32 ssic:1; /* suppress-suspended-interr. control */ | ||
29 | u32 res2:1; /* reserved */ | ||
30 | u32 c64:1; /* IDAW/QDIO 64 bit control */ | ||
31 | u32 i2k:1; /* IDAW 2/4kB block size control */ | ||
32 | u32 lpm:8; /* logical path mask */ | ||
33 | u32 ils:1; /* incorrect length */ | ||
34 | u32 zero:6; /* reserved zeros */ | ||
35 | u32 orbx:1; /* ORB extension control */ | ||
36 | u32 cpa; /* channel program address */ | ||
37 | } __packed __aligned(4); | ||
38 | |||
39 | /* | ||
40 | * Transport-mode operation request block | ||
41 | */ | ||
42 | struct tm_orb { | ||
43 | u32 intparm; | ||
44 | u32 key:4; | ||
45 | u32:9; | ||
46 | u32 b:1; | ||
47 | u32:2; | ||
48 | u32 lpm:8; | ||
49 | u32:7; | ||
50 | u32 x:1; | ||
51 | u32 tcw; | ||
52 | u32 prio:8; | ||
53 | u32:8; | ||
54 | u32 rsvpgm:8; | ||
55 | u32:8; | ||
56 | u32:32; | ||
57 | u32:32; | ||
58 | u32:32; | ||
59 | u32:32; | ||
60 | } __packed __aligned(4); | ||
61 | |||
62 | union orb { | ||
63 | struct cmd_orb cmd; | ||
64 | struct tm_orb tm; | ||
65 | } __packed __aligned(4); | ||
66 | |||
67 | #endif /* S390_ORB_H */ | ||