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 */ | ||
