aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2008-01-26 08:10:43 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-01-26 08:10:59 -0500
commitcd6b4f27b9bb2a6a5ec82b96b87c85421257be6c (patch)
treebf5ac3d351242de6438ab1453a7f1b007f24c29f /drivers/s390/cio
parentbc698bcf8897363732226dc9ecba044771679996 (diff)
[S390] cio: Introduce subchannel->private.
Introduce a private pointer in struct subchannel to store per-subchannel type data (cannot use dev->priv since this is already used for something else). Create a new header io_sch.h for I/O subchannel specific structures and instructions. Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/cio.c43
-rw-r--r--drivers/s390/cio/cio.h84
-rw-r--r--drivers/s390/cio/css.c2
-rw-r--r--drivers/s390/cio/css.h58
-rw-r--r--drivers/s390/cio/device.c16
-rw-r--r--drivers/s390/cio/device.h2
-rw-r--r--drivers/s390/cio/device_fsm.c13
-rw-r--r--drivers/s390/cio/device_id.c9
-rw-r--r--drivers/s390/cio/device_pgid.c6
-rw-r--r--drivers/s390/cio/device_status.c13
-rw-r--r--drivers/s390/cio/io_sch.h161
-rw-r--r--drivers/s390/cio/ioasm.h66
12 files changed, 261 insertions, 212 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index cd5475b82420..d0bcebde3fa2 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -28,6 +28,7 @@
28#include "css.h" 28#include "css.h"
29#include "chsc.h" 29#include "chsc.h"
30#include "ioasm.h" 30#include "ioasm.h"
31#include "io_sch.h"
31#include "blacklist.h" 32#include "blacklist.h"
32#include "cio_debug.h" 33#include "cio_debug.h"
33#include "chp.h" 34#include "chp.h"
@@ -182,33 +183,35 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
182{ 183{
183 char dbf_txt[15]; 184 char dbf_txt[15];
184 int ccode; 185 int ccode;
186 struct orb *orb;
185 187
186 CIO_TRACE_EVENT (4, "stIO"); 188 CIO_TRACE_EVENT(4, "stIO");
187 CIO_TRACE_EVENT (4, sch->dev.bus_id); 189 CIO_TRACE_EVENT(4, sch->dev.bus_id);
188 190
191 orb = &to_io_private(sch)->orb;
189 /* sch is always under 2G. */ 192 /* sch is always under 2G. */
190 sch->orb.intparm = (__u32)(unsigned long)sch; 193 orb->intparm = (u32)(addr_t)sch;
191 sch->orb.fmt = 1; 194 orb->fmt = 1;
192 195
193 sch->orb.pfch = sch->options.prefetch == 0; 196 orb->pfch = sch->options.prefetch == 0;
194 sch->orb.spnd = sch->options.suspend; 197 orb->spnd = sch->options.suspend;
195 sch->orb.ssic = sch->options.suspend && sch->options.inter; 198 orb->ssic = sch->options.suspend && sch->options.inter;
196 sch->orb.lpm = (lpm != 0) ? lpm : sch->lpm; 199 orb->lpm = (lpm != 0) ? lpm : sch->lpm;
197#ifdef CONFIG_64BIT 200#ifdef CONFIG_64BIT
198 /* 201 /*
199 * for 64 bit we always support 64 bit IDAWs with 4k page size only 202 * for 64 bit we always support 64 bit IDAWs with 4k page size only
200 */ 203 */
201 sch->orb.c64 = 1; 204 orb->c64 = 1;
202 sch->orb.i2k = 0; 205 orb->i2k = 0;
203#endif 206#endif
204 sch->orb.key = key >> 4; 207 orb->key = key >> 4;
205 /* issue "Start Subchannel" */ 208 /* issue "Start Subchannel" */
206 sch->orb.cpa = (__u32) __pa (cpa); 209 orb->cpa = (__u32) __pa(cpa);
207 ccode = ssch (sch->schid, &sch->orb); 210 ccode = ssch(sch->schid, orb);
208 211
209 /* process condition code */ 212 /* process condition code */
210 sprintf (dbf_txt, "ccode:%d", ccode); 213 sprintf(dbf_txt, "ccode:%d", ccode);
211 CIO_TRACE_EVENT (4, dbf_txt); 214 CIO_TRACE_EVENT(4, dbf_txt);
212 215
213 switch (ccode) { 216 switch (ccode) {
214 case 0: 217 case 0:
@@ -423,7 +426,7 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
423 for (retry = 5, ret = 0; retry > 0; retry--) { 426 for (retry = 5, ret = 0; retry > 0; retry--) {
424 sch->schib.pmcw.ena = 1; 427 sch->schib.pmcw.ena = 1;
425 sch->schib.pmcw.isc = isc; 428 sch->schib.pmcw.isc = isc;
426 sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; 429 sch->schib.pmcw.intparm = (u32)(addr_t)sch;
427 ret = cio_modify(sch); 430 ret = cio_modify(sch);
428 if (ret == -ENODEV) 431 if (ret == -ENODEV)
429 break; 432 break;
@@ -696,8 +699,14 @@ do_IRQ (struct pt_regs *regs)
696 699
697#ifdef CONFIG_CCW_CONSOLE 700#ifdef CONFIG_CCW_CONSOLE
698static struct subchannel console_subchannel; 701static struct subchannel console_subchannel;
702static struct io_subchannel_private console_priv;
699static int console_subchannel_in_use; 703static int console_subchannel_in_use;
700 704
705void *cio_get_console_priv(void)
706{
707 return &console_priv;
708}
709
701/* 710/*
702 * busy wait for the next interrupt on the console 711 * busy wait for the next interrupt on the console
703 */ 712 */
@@ -802,7 +811,7 @@ cio_probe_console(void)
802 ctl_set_bit(6, 24); 811 ctl_set_bit(6, 24);
803 console_subchannel.schib.pmcw.isc = 7; 812 console_subchannel.schib.pmcw.isc = 7;
804 console_subchannel.schib.pmcw.intparm = 813 console_subchannel.schib.pmcw.intparm =
805 (__u32)(unsigned long)&console_subchannel; 814 (u32)(addr_t)&console_subchannel;
806 ret = cio_modify(&console_subchannel); 815 ret = cio_modify(&console_subchannel);
807 if (ret) { 816 if (ret) {
808 console_subchannel_in_use = 0; 817 console_subchannel_in_use = 0;
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 7446c39951a7..a6ef218defbe 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -11,32 +11,32 @@
11 * path management control word 11 * path management control word
12 */ 12 */
13struct pmcw { 13struct pmcw {
14 __u32 intparm; /* interruption parameter */ 14 u32 intparm; /* interruption parameter */
15 __u32 qf : 1; /* qdio facility */ 15 u32 qf : 1; /* qdio facility */
16 __u32 res0 : 1; /* reserved zeros */ 16 u32 res0 : 1; /* reserved zeros */
17 __u32 isc : 3; /* interruption sublass */ 17 u32 isc : 3; /* interruption sublass */
18 __u32 res5 : 3; /* reserved zeros */ 18 u32 res5 : 3; /* reserved zeros */
19 __u32 ena : 1; /* enabled */ 19 u32 ena : 1; /* enabled */
20 __u32 lm : 2; /* limit mode */ 20 u32 lm : 2; /* limit mode */
21 __u32 mme : 2; /* measurement-mode enable */ 21 u32 mme : 2; /* measurement-mode enable */
22 __u32 mp : 1; /* multipath mode */ 22 u32 mp : 1; /* multipath mode */
23 __u32 tf : 1; /* timing facility */ 23 u32 tf : 1; /* timing facility */
24 __u32 dnv : 1; /* device number valid */ 24 u32 dnv : 1; /* device number valid */
25 __u32 dev : 16; /* device number */ 25 u32 dev : 16; /* device number */
26 __u8 lpm; /* logical path mask */ 26 u8 lpm; /* logical path mask */
27 __u8 pnom; /* path not operational mask */ 27 u8 pnom; /* path not operational mask */
28 __u8 lpum; /* last path used mask */ 28 u8 lpum; /* last path used mask */
29 __u8 pim; /* path installed mask */ 29 u8 pim; /* path installed mask */
30 __u16 mbi; /* measurement-block index */ 30 u16 mbi; /* measurement-block index */
31 __u8 pom; /* path operational mask */ 31 u8 pom; /* path operational mask */
32 __u8 pam; /* path available mask */ 32 u8 pam; /* path available mask */
33 __u8 chpid[8]; /* CHPID 0-7 (if available) */ 33 u8 chpid[8]; /* CHPID 0-7 (if available) */
34 __u32 unused1 : 8; /* reserved zeros */ 34 u32 unused1 : 8; /* reserved zeros */
35 __u32 st : 3; /* subchannel type */ 35 u32 st : 3; /* subchannel type */
36 __u32 unused2 : 18; /* reserved zeros */ 36 u32 unused2 : 18; /* reserved zeros */
37 __u32 mbfc : 1; /* measurement block format control */ 37 u32 mbfc : 1; /* measurement block format control */
38 __u32 xmwme : 1; /* extended measurement word mode enable */ 38 u32 xmwme : 1; /* extended measurement word mode enable */
39 __u32 csense : 1; /* concurrent sense; can be enabled ...*/ 39 u32 csense : 1; /* concurrent sense; can be enabled ...*/
40 /* ... per MSCH, however, if facility */ 40 /* ... per MSCH, however, if facility */
41 /* ... is not installed, this results */ 41 /* ... is not installed, this results */
42 /* ... in an operand exception. */ 42 /* ... in an operand exception. */
@@ -52,31 +52,6 @@ struct schib {
52 __u8 mda[4]; /* model dependent area */ 52 __u8 mda[4]; /* model dependent area */
53} __attribute__ ((packed,aligned(4))); 53} __attribute__ ((packed,aligned(4)));
54 54
55/*
56 * operation request block
57 */
58struct orb {
59 __u32 intparm; /* interruption parameter */
60 __u32 key : 4; /* flags, like key, suspend control, etc. */
61 __u32 spnd : 1; /* suspend control */
62 __u32 res1 : 1; /* reserved */
63 __u32 mod : 1; /* modification control */
64 __u32 sync : 1; /* synchronize control */
65 __u32 fmt : 1; /* format control */
66 __u32 pfch : 1; /* prefetch control */
67 __u32 isic : 1; /* initial-status-interruption control */
68 __u32 alcc : 1; /* address-limit-checking control */
69 __u32 ssic : 1; /* suppress-suspended-interr. control */
70 __u32 res2 : 1; /* reserved */
71 __u32 c64 : 1; /* IDAW/QDIO 64 bit control */
72 __u32 i2k : 1; /* IDAW 2/4kB block size control */
73 __u32 lpm : 8; /* logical path mask */
74 __u32 ils : 1; /* incorrect length */
75 __u32 zero : 6; /* reserved zeros */
76 __u32 orbx : 1; /* ORB extension control */
77 __u32 cpa; /* channel program address */
78} __attribute__ ((packed,aligned(4)));
79
80/* subchannel data structure used by I/O subroutines */ 55/* subchannel data structure used by I/O subroutines */
81struct subchannel { 56struct subchannel {
82 struct subchannel_id schid; 57 struct subchannel_id schid;
@@ -99,11 +74,10 @@ struct subchannel {
99 __u8 lpm; /* logical path mask */ 74 __u8 lpm; /* logical path mask */
100 __u8 opm; /* operational path mask */ 75 __u8 opm; /* operational path mask */
101 struct schib schib; /* subchannel information block */ 76 struct schib schib; /* subchannel information block */
102 struct orb orb; /* operation request block */
103 struct ccw1 sense_ccw; /* static ccw for sense command */
104 struct chsc_ssd_info ssd_info; /* subchannel description */ 77 struct chsc_ssd_info ssd_info; /* subchannel description */
105 struct device dev; /* entry in device tree */ 78 struct device dev; /* entry in device tree */
106 struct css_driver *driver; 79 struct css_driver *driver;
80 void *private; /* private per subchannel type data */
107} __attribute__ ((aligned(8))); 81} __attribute__ ((aligned(8)));
108 82
109#define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */ 83#define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */
@@ -133,10 +107,12 @@ extern void cio_release_console(void);
133extern int cio_is_console(struct subchannel_id); 107extern int cio_is_console(struct subchannel_id);
134extern struct subchannel *cio_get_console_subchannel(void); 108extern struct subchannel *cio_get_console_subchannel(void);
135extern spinlock_t * cio_get_console_lock(void); 109extern spinlock_t * cio_get_console_lock(void);
110extern void *cio_get_console_priv(void);
136#else 111#else
137#define cio_is_console(schid) 0 112#define cio_is_console(schid) 0
138#define cio_get_console_subchannel() NULL 113#define cio_get_console_subchannel() NULL
139#define cio_get_console_lock() NULL; 114#define cio_get_console_lock() NULL
115#define cio_get_console_priv() NULL
140#endif 116#endif
141 117
142extern int cio_show_msg; 118extern int cio_show_msg;
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 7d887f88bb73..2520a44fb93d 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -77,7 +77,7 @@ css_alloc_subchannel(struct subchannel_id schid)
77 * This is fine even on 64bit since the subchannel is always located 77 * This is fine even on 64bit since the subchannel is always located
78 * under 2G. 78 * under 2G.
79 */ 79 */
80 sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; 80 sch->schib.pmcw.intparm = (u32)(addr_t)sch;
81 ret = cio_modify(sch); 81 ret = cio_modify(sch);
82 if (ret) { 82 if (ret) {
83 kfree(sch->lock); 83 kfree(sch->lock);
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index c9fd600411c4..b2b4a30c285e 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -58,64 +58,6 @@ struct pgid {
58 __u32 tod_high; /* high word TOD clock */ 58 __u32 tod_high; /* high word TOD clock */
59} __attribute__ ((packed)); 59} __attribute__ ((packed));
60 60
61#define MAX_CIWS 8
62
63/*
64 * sense-id response buffer layout
65 */
66struct senseid {
67 /* common part */
68 __u8 reserved; /* always 0x'FF' */
69 __u16 cu_type; /* control unit type */
70 __u8 cu_model; /* control unit model */
71 __u16 dev_type; /* device type */
72 __u8 dev_model; /* device model */
73 __u8 unused; /* padding byte */
74 /* extended part */
75 struct ciw ciw[MAX_CIWS]; /* variable # of CIWs */
76} __attribute__ ((packed,aligned(4)));
77
78struct ccw_device_private {
79 struct ccw_device *cdev;
80 struct subchannel *sch;
81 int state; /* device state */
82 atomic_t onoff;
83 unsigned long registered;
84 struct ccw_dev_id dev_id; /* device id */
85 struct subchannel_id schid; /* subchannel number */
86 __u8 imask; /* lpm mask for SNID/SID/SPGID */
87 int iretry; /* retry counter SNID/SID/SPGID */
88 struct {
89 unsigned int fast:1; /* post with "channel end" */
90 unsigned int repall:1; /* report every interrupt status */
91 unsigned int pgroup:1; /* do path grouping */
92 unsigned int force:1; /* allow forced online */
93 } __attribute__ ((packed)) options;
94 struct {
95 unsigned int pgid_single:1; /* use single path for Set PGID */
96 unsigned int esid:1; /* Ext. SenseID supported by HW */
97 unsigned int dosense:1; /* delayed SENSE required */
98 unsigned int doverify:1; /* delayed path verification */
99 unsigned int donotify:1; /* call notify function */
100 unsigned int recog_done:1; /* dev. recog. complete */
101 unsigned int fake_irb:1; /* deliver faked irb */
102 unsigned int intretry:1; /* retry internal operation */
103 } __attribute__((packed)) flags;
104 unsigned long intparm; /* user interruption parameter */
105 struct qdio_irq *qdio_data;
106 struct irb irb; /* device status */
107 struct senseid senseid; /* SenseID info */
108 struct pgid pgid[8]; /* path group IDs per chpid*/
109 struct ccw1 iccws[2]; /* ccws for SNID/SID/SPGID commands */
110 struct work_struct kick_work;
111 wait_queue_head_t wait_q;
112 struct timer_list timer;
113 void *cmb; /* measurement information */
114 struct list_head cmb_list; /* list of measured devices */
115 u64 cmb_start_time; /* clock value of cmb reset */
116 void *cmb_wait; /* deferred cmb enable/disable */
117};
118
119/* 61/*
120 * A css driver handles all subchannels of one type. 62 * A css driver handles all subchannels of one type.
121 * Currently, we only care about I/O subchannels (type 0), these 63 * Currently, we only care about I/O subchannels (type 0), these
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 7bccca9684e5..30fe59cc28c9 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -28,6 +28,7 @@
28#include "css.h" 28#include "css.h"
29#include "device.h" 29#include "device.h"
30#include "ioasm.h" 30#include "ioasm.h"
31#include "io_sch.h"
31 32
32/******************* bus type handling ***********************/ 33/******************* bus type handling ***********************/
33 34
@@ -1143,6 +1144,11 @@ io_subchannel_probe (struct subchannel *sch)
1143 */ 1144 */
1144 dev_id.devno = sch->schib.pmcw.dev; 1145 dev_id.devno = sch->schib.pmcw.dev;
1145 dev_id.ssid = sch->schid.ssid; 1146 dev_id.ssid = sch->schid.ssid;
1147 /* Allocate I/O subchannel private data. */
1148 sch->private = kzalloc(sizeof(struct io_subchannel_private),
1149 GFP_KERNEL | GFP_DMA);
1150 if (!sch->private)
1151 return -ENOMEM;
1146 cdev = get_disc_ccwdev_by_dev_id(&dev_id, NULL); 1152 cdev = get_disc_ccwdev_by_dev_id(&dev_id, NULL);
1147 if (!cdev) 1153 if (!cdev)
1148 cdev = get_orphaned_ccwdev_by_dev_id(to_css(sch->dev.parent), 1154 cdev = get_orphaned_ccwdev_by_dev_id(to_css(sch->dev.parent),
@@ -1160,9 +1166,10 @@ io_subchannel_probe (struct subchannel *sch)
1160 return 0; 1166 return 0;
1161 } 1167 }
1162 cdev = io_subchannel_create_ccwdev(sch); 1168 cdev = io_subchannel_create_ccwdev(sch);
1163 if (IS_ERR(cdev)) 1169 if (IS_ERR(cdev)) {
1170 kfree(sch->private);
1164 return PTR_ERR(cdev); 1171 return PTR_ERR(cdev);
1165 1172 }
1166 rc = io_subchannel_recog(cdev, sch); 1173 rc = io_subchannel_recog(cdev, sch);
1167 if (rc) { 1174 if (rc) {
1168 spin_lock_irqsave(sch->lock, flags); 1175 spin_lock_irqsave(sch->lock, flags);
@@ -1170,6 +1177,7 @@ io_subchannel_probe (struct subchannel *sch)
1170 spin_unlock_irqrestore(sch->lock, flags); 1177 spin_unlock_irqrestore(sch->lock, flags);
1171 if (cdev->dev.release) 1178 if (cdev->dev.release)
1172 cdev->dev.release(&cdev->dev); 1179 cdev->dev.release(&cdev->dev);
1180 kfree(sch->private);
1173 } 1181 }
1174 1182
1175 return rc; 1183 return rc;
@@ -1191,6 +1199,7 @@ io_subchannel_remove (struct subchannel *sch)
1191 spin_unlock_irqrestore(cdev->ccwlock, flags); 1199 spin_unlock_irqrestore(cdev->ccwlock, flags);
1192 ccw_device_unregister(cdev); 1200 ccw_device_unregister(cdev);
1193 put_device(&cdev->dev); 1201 put_device(&cdev->dev);
1202 kfree(sch->private);
1194 return 0; 1203 return 0;
1195} 1204}
1196 1205
@@ -1279,6 +1288,9 @@ ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
1279{ 1288{
1280 int rc; 1289 int rc;
1281 1290
1291 /* Attach subchannel private data. */
1292 sch->private = cio_get_console_priv();
1293 memset(sch->private, 0, sizeof(struct io_subchannel_private));
1282 /* Initialize the ccw_device structure. */ 1294 /* Initialize the ccw_device structure. */
1283 cdev->dev.parent= &sch->dev; 1295 cdev->dev.parent= &sch->dev;
1284 rc = io_subchannel_recog(cdev, sch); 1296 rc = io_subchannel_recog(cdev, sch);
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 6183731fb9a2..87576fe2c7c4 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -5,6 +5,8 @@
5#include <asm/atomic.h> 5#include <asm/atomic.h>
6#include <linux/wait.h> 6#include <linux/wait.h>
7 7
8#include "io_sch.h"
9
8/* 10/*
9 * states of the device statemachine 11 * states of the device statemachine
10 */ 12 */
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 8b6be2142c81..44ce7a3d3857 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -96,29 +96,32 @@ static void ccw_timeout_log(struct ccw_device *cdev)
96{ 96{
97 struct schib schib; 97 struct schib schib;
98 struct subchannel *sch; 98 struct subchannel *sch;
99 struct io_subchannel_private *private;
99 int cc; 100 int cc;
100 101
101 sch = to_subchannel(cdev->dev.parent); 102 sch = to_subchannel(cdev->dev.parent);
103 private = to_io_private(sch);
102 cc = stsch(sch->schid, &schib); 104 cc = stsch(sch->schid, &schib);
103 105
104 printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, " 106 printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, "
105 "device information:\n", get_clock()); 107 "device information:\n", get_clock());
106 printk(KERN_WARNING "cio: orb:\n"); 108 printk(KERN_WARNING "cio: orb:\n");
107 print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1, 109 print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1,
108 &sch->orb, sizeof(sch->orb), 0); 110 &private->orb, sizeof(private->orb), 0);
109 printk(KERN_WARNING "cio: ccw device bus id: %s\n", cdev->dev.bus_id); 111 printk(KERN_WARNING "cio: ccw device bus id: %s\n", cdev->dev.bus_id);
110 printk(KERN_WARNING "cio: subchannel bus id: %s\n", sch->dev.bus_id); 112 printk(KERN_WARNING "cio: subchannel bus id: %s\n", sch->dev.bus_id);
111 printk(KERN_WARNING "cio: subchannel lpm: %02x, opm: %02x, " 113 printk(KERN_WARNING "cio: subchannel lpm: %02x, opm: %02x, "
112 "vpm: %02x\n", sch->lpm, sch->opm, sch->vpm); 114 "vpm: %02x\n", sch->lpm, sch->opm, sch->vpm);
113 115
114 if ((void *)(addr_t)sch->orb.cpa == &sch->sense_ccw || 116 if ((void *)(addr_t)private->orb.cpa == &private->sense_ccw ||
115 (void *)(addr_t)sch->orb.cpa == cdev->private->iccws) 117 (void *)(addr_t)private->orb.cpa == cdev->private->iccws)
116 printk(KERN_WARNING "cio: last channel program (intern):\n"); 118 printk(KERN_WARNING "cio: last channel program (intern):\n");
117 else 119 else
118 printk(KERN_WARNING "cio: last channel program:\n"); 120 printk(KERN_WARNING "cio: last channel program:\n");
119 121
120 print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1, 122 print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1,
121 (void *)(addr_t)sch->orb.cpa, sizeof(struct ccw1), 0); 123 (void *)(addr_t)private->orb.cpa,
124 sizeof(struct ccw1), 0);
122 printk(KERN_WARNING "cio: ccw device state: %d\n", 125 printk(KERN_WARNING "cio: ccw device state: %d\n",
123 cdev->private->state); 126 cdev->private->state);
124 printk(KERN_WARNING "cio: store subchannel returned: cc=%d\n", cc); 127 printk(KERN_WARNING "cio: store subchannel returned: cc=%d\n", cc);
@@ -1078,7 +1081,7 @@ device_trigger_reprobe(struct subchannel *sch)
1078 sch->schib.pmcw.ena = 0; 1081 sch->schib.pmcw.ena = 0;
1079 if ((sch->lpm & (sch->lpm - 1)) != 0) 1082 if ((sch->lpm & (sch->lpm - 1)) != 0)
1080 sch->schib.pmcw.mp = 1; 1083 sch->schib.pmcw.mp = 1;
1081 sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; 1084 sch->schib.pmcw.intparm = (u32)(addr_t)sch;
1082 /* We should also udate ssd info, but this has to wait. */ 1085 /* We should also udate ssd info, but this has to wait. */
1083 /* Check if this is another device which appeared on the same sch. */ 1086 /* Check if this is another device which appeared on the same sch. */
1084 if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { 1087 if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 156f3f9786b5..918b8b89cf9a 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -24,6 +24,7 @@
24#include "css.h" 24#include "css.h"
25#include "device.h" 25#include "device.h"
26#include "ioasm.h" 26#include "ioasm.h"
27#include "io_sch.h"
27 28
28/* 29/*
29 * Input : 30 * Input :
@@ -219,11 +220,13 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
219 return -EAGAIN; 220 return -EAGAIN;
220 } 221 }
221 if (irb->scsw.cc == 3) { 222 if (irb->scsw.cc == 3) {
222 if ((sch->orb.lpm & 223 u8 lpm;
223 sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0) 224
225 lpm = to_io_private(sch)->orb.lpm;
226 if ((lpm & sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0)
224 CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x " 227 CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x "
225 "on subchannel 0.%x.%04x is " 228 "on subchannel 0.%x.%04x is "
226 "'not operational'\n", sch->orb.lpm, 229 "'not operational'\n", lpm,
227 cdev->private->dev_id.devno, 230 cdev->private->dev_id.devno,
228 sch->schid.ssid, sch->schid.sch_no); 231 sch->schid.ssid, sch->schid.sch_no);
229 return -EACCES; 232 return -EACCES;
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index cb1879a96818..c52449a1f9fc 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -22,6 +22,7 @@
22#include "css.h" 22#include "css.h"
23#include "device.h" 23#include "device.h"
24#include "ioasm.h" 24#include "ioasm.h"
25#include "io_sch.h"
25 26
26/* 27/*
27 * Helper function called from interrupt context to decide whether an 28 * Helper function called from interrupt context to decide whether an
@@ -155,10 +156,13 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
155 return -EAGAIN; 156 return -EAGAIN;
156 } 157 }
157 if (irb->scsw.cc == 3) { 158 if (irb->scsw.cc == 3) {
159 u8 lpm;
160
161 lpm = to_io_private(sch)->orb.lpm;
158 CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x," 162 CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
159 " lpm %02X, became 'not operational'\n", 163 " lpm %02X, became 'not operational'\n",
160 cdev->private->dev_id.devno, sch->schid.ssid, 164 cdev->private->dev_id.devno, sch->schid.ssid,
161 sch->schid.sch_no, sch->orb.lpm); 165 sch->schid.sch_no, lpm);
162 return -EACCES; 166 return -EACCES;
163 } 167 }
164 i = 8 - ffs(cdev->private->imask); 168 i = 8 - ffs(cdev->private->imask);
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index aa96e6752592..ebe0848cfe33 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -20,6 +20,7 @@
20#include "css.h" 20#include "css.h"
21#include "device.h" 21#include "device.h"
22#include "ioasm.h" 22#include "ioasm.h"
23#include "io_sch.h"
23 24
24/* 25/*
25 * Check for any kind of channel or interface control check but don't 26 * Check for any kind of channel or interface control check but don't
@@ -310,6 +311,7 @@ int
310ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb) 311ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
311{ 312{
312 struct subchannel *sch; 313 struct subchannel *sch;
314 struct ccw1 *sense_ccw;
313 315
314 sch = to_subchannel(cdev->dev.parent); 316 sch = to_subchannel(cdev->dev.parent);
315 317
@@ -326,15 +328,16 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
326 /* 328 /*
327 * We have ending status but no sense information. Do a basic sense. 329 * We have ending status but no sense information. Do a basic sense.
328 */ 330 */
329 sch->sense_ccw.cmd_code = CCW_CMD_BASIC_SENSE; 331 sense_ccw = &to_io_private(sch)->sense_ccw;
330 sch->sense_ccw.cda = (__u32) __pa(cdev->private->irb.ecw); 332 sense_ccw->cmd_code = CCW_CMD_BASIC_SENSE;
331 sch->sense_ccw.count = SENSE_MAX_COUNT; 333 sense_ccw->cda = (__u32) __pa(cdev->private->irb.ecw);
332 sch->sense_ccw.flags = CCW_FLAG_SLI; 334 sense_ccw->count = SENSE_MAX_COUNT;
335 sense_ccw->flags = CCW_FLAG_SLI;
333 336
334 /* Reset internal retry indication. */ 337 /* Reset internal retry indication. */
335 cdev->private->flags.intretry = 0; 338 cdev->private->flags.intretry = 0;
336 339
337 return cio_start (sch, &sch->sense_ccw, 0xff); 340 return cio_start(sch, sense_ccw, 0xff);
338} 341}
339 342
340/* 343/*
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
new file mode 100644
index 000000000000..d49e5a77a6bf
--- /dev/null
+++ b/drivers/s390/cio/io_sch.h
@@ -0,0 +1,161 @@
1#ifndef S390_IO_SCH_H
2#define S390_IO_SCH_H
3
4#include "schid.h"
5
6/*
7 * operation request block
8 */
9struct orb {
10 u32 intparm; /* interruption parameter */
11 u32 key : 4; /* flags, like key, suspend control, etc. */
12 u32 spnd : 1; /* suspend control */
13 u32 res1 : 1; /* reserved */
14 u32 mod : 1; /* modification control */
15 u32 sync : 1; /* synchronize control */
16 u32 fmt : 1; /* format control */
17 u32 pfch : 1; /* prefetch control */
18 u32 isic : 1; /* initial-status-interruption control */
19 u32 alcc : 1; /* address-limit-checking control */
20 u32 ssic : 1; /* suppress-suspended-interr. control */
21 u32 res2 : 1; /* reserved */
22 u32 c64 : 1; /* IDAW/QDIO 64 bit control */
23 u32 i2k : 1; /* IDAW 2/4kB block size control */
24 u32 lpm : 8; /* logical path mask */
25 u32 ils : 1; /* incorrect length */
26 u32 zero : 6; /* reserved zeros */
27 u32 orbx : 1; /* ORB extension control */
28 u32 cpa; /* channel program address */
29} __attribute__ ((packed, aligned(4)));
30
31struct io_subchannel_private {
32 struct orb orb; /* operation request block */
33 struct ccw1 sense_ccw; /* static ccw for sense command */
34} __attribute__ ((aligned(8)));
35
36#define to_io_private(n) ((struct io_subchannel_private *)n->private)
37
38#define MAX_CIWS 8
39
40/*
41 * sense-id response buffer layout
42 */
43struct senseid {
44 /* common part */
45 u8 reserved; /* always 0x'FF' */
46 u16 cu_type; /* control unit type */
47 u8 cu_model; /* control unit model */
48 u16 dev_type; /* device type */
49 u8 dev_model; /* device model */
50 u8 unused; /* padding byte */
51 /* extended part */
52 struct ciw ciw[MAX_CIWS]; /* variable # of CIWs */
53} __attribute__ ((packed, aligned(4)));
54
55struct ccw_device_private {
56 struct ccw_device *cdev;
57 struct subchannel *sch;
58 int state; /* device state */
59 atomic_t onoff;
60 unsigned long registered;
61 struct ccw_dev_id dev_id; /* device id */
62 struct subchannel_id schid; /* subchannel number */
63 u8 imask; /* lpm mask for SNID/SID/SPGID */
64 int iretry; /* retry counter SNID/SID/SPGID */
65 struct {
66 unsigned int fast:1; /* post with "channel end" */
67 unsigned int repall:1; /* report every interrupt status */
68 unsigned int pgroup:1; /* do path grouping */
69 unsigned int force:1; /* allow forced online */
70 } __attribute__ ((packed)) options;
71 struct {
72 unsigned int pgid_single:1; /* use single path for Set PGID */
73 unsigned int esid:1; /* Ext. SenseID supported by HW */
74 unsigned int dosense:1; /* delayed SENSE required */
75 unsigned int doverify:1; /* delayed path verification */
76 unsigned int donotify:1; /* call notify function */
77 unsigned int recog_done:1; /* dev. recog. complete */
78 unsigned int fake_irb:1; /* deliver faked irb */
79 unsigned int intretry:1; /* retry internal operation */
80 } __attribute__((packed)) flags;
81 unsigned long intparm; /* user interruption parameter */
82 struct qdio_irq *qdio_data;
83 struct irb irb; /* device status */
84 struct senseid senseid; /* SenseID info */
85 struct pgid pgid[8]; /* path group IDs per chpid*/
86 struct ccw1 iccws[2]; /* ccws for SNID/SID/SPGID commands */
87 struct work_struct kick_work;
88 wait_queue_head_t wait_q;
89 struct timer_list timer;
90 void *cmb; /* measurement information */
91 struct list_head cmb_list; /* list of measured devices */
92 u64 cmb_start_time; /* clock value of cmb reset */
93 void *cmb_wait; /* deferred cmb enable/disable */
94};
95
96static inline int ssch(struct subchannel_id schid, volatile struct orb *addr)
97{
98 register struct subchannel_id reg1 asm("1") = schid;
99 int ccode;
100
101 asm volatile(
102 " ssch 0(%2)\n"
103 " ipm %0\n"
104 " srl %0,28"
105 : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
106 return ccode;
107}
108
109static inline int rsch(struct subchannel_id schid)
110{
111 register struct subchannel_id reg1 asm("1") = schid;
112 int ccode;
113
114 asm volatile(
115 " rsch\n"
116 " ipm %0\n"
117 " srl %0,28"
118 : "=d" (ccode) : "d" (reg1) : "cc");
119 return ccode;
120}
121
122static inline int csch(struct subchannel_id schid)
123{
124 register struct subchannel_id reg1 asm("1") = schid;
125 int ccode;
126
127 asm volatile(
128 " csch\n"
129 " ipm %0\n"
130 " srl %0,28"
131 : "=d" (ccode) : "d" (reg1) : "cc");
132 return ccode;
133}
134
135static inline int hsch(struct subchannel_id schid)
136{
137 register struct subchannel_id reg1 asm("1") = schid;
138 int ccode;
139
140 asm volatile(
141 " hsch\n"
142 " ipm %0\n"
143 " srl %0,28"
144 : "=d" (ccode) : "d" (reg1) : "cc");
145 return ccode;
146}
147
148static inline int xsch(struct subchannel_id schid)
149{
150 register struct subchannel_id reg1 asm("1") = schid;
151 int ccode;
152
153 asm volatile(
154 " .insn rre,0xb2760000,%1,0\n"
155 " ipm %0\n"
156 " srl %0,28"
157 : "=d" (ccode) : "d" (reg1) : "cc");
158 return ccode;
159}
160
161#endif
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index 7153dd959082..652ea3625f9d 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -109,72 +109,6 @@ static inline int tpi( volatile struct tpi_info *addr)
109 return ccode; 109 return ccode;
110} 110}
111 111
112static inline int ssch(struct subchannel_id schid,
113 volatile struct orb *addr)
114{
115 register struct subchannel_id reg1 asm ("1") = schid;
116 int ccode;
117
118 asm volatile(
119 " ssch 0(%2)\n"
120 " ipm %0\n"
121 " srl %0,28"
122 : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
123 return ccode;
124}
125
126static inline int rsch(struct subchannel_id schid)
127{
128 register struct subchannel_id reg1 asm ("1") = schid;
129 int ccode;
130
131 asm volatile(
132 " rsch\n"
133 " ipm %0\n"
134 " srl %0,28"
135 : "=d" (ccode) : "d" (reg1) : "cc");
136 return ccode;
137}
138
139static inline int csch(struct subchannel_id schid)
140{
141 register struct subchannel_id reg1 asm ("1") = schid;
142 int ccode;
143
144 asm volatile(
145 " csch\n"
146 " ipm %0\n"
147 " srl %0,28"
148 : "=d" (ccode) : "d" (reg1) : "cc");
149 return ccode;
150}
151
152static inline int hsch(struct subchannel_id schid)
153{
154 register struct subchannel_id reg1 asm ("1") = schid;
155 int ccode;
156
157 asm volatile(
158 " hsch\n"
159 " ipm %0\n"
160 " srl %0,28"
161 : "=d" (ccode) : "d" (reg1) : "cc");
162 return ccode;
163}
164
165static inline int xsch(struct subchannel_id schid)
166{
167 register struct subchannel_id reg1 asm ("1") = schid;
168 int ccode;
169
170 asm volatile(
171 " .insn rre,0xb2760000,%1,0\n"
172 " ipm %0\n"
173 " srl %0,28"
174 : "=d" (ccode) : "d" (reg1) : "cc");
175 return ccode;
176}
177
178static inline int chsc(void *chsc_area) 112static inline int chsc(void *chsc_area)
179{ 113{
180 typedef struct { char _[4096]; } addr_type; 114 typedef struct { char _[4096]; } addr_type;