aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/Kconfig2
-rw-r--r--drivers/s390/block/dasd.c19
-rw-r--r--drivers/s390/block/dasd_devmap.c8
-rw-r--r--drivers/s390/block/dasd_diag.c334
-rw-r--r--drivers/s390/block/dasd_diag.h105
-rw-r--r--drivers/s390/block/dasd_genhd.c10
-rw-r--r--drivers/s390/block/dasd_int.h3
-rw-r--r--drivers/s390/block/dasd_ioctl.c17
-rw-r--r--drivers/s390/block/dasd_proc.c8
-rw-r--r--drivers/s390/char/raw3270.c16
-rw-r--r--drivers/s390/cio/cio.c7
-rw-r--r--drivers/s390/cio/device_fsm.c3
-rw-r--r--drivers/s390/cio/device_ops.c4
-rw-r--r--drivers/s390/cio/ioasm.h26
-rw-r--r--drivers/s390/crypto/z90common.h3
-rw-r--r--drivers/s390/crypto/z90hardware.c127
-rw-r--r--drivers/s390/crypto/z90main.c246
-rw-r--r--drivers/s390/net/claw.c20
-rw-r--r--drivers/s390/s390mach.c2
19 files changed, 478 insertions, 482 deletions
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index dc1c89dbdb8f..6e7d7b06421d 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -49,7 +49,7 @@ config DASD_FBA
49 49
50config DASD_DIAG 50config DASD_DIAG
51 tristate "Support for DIAG access to Disks" 51 tristate "Support for DIAG access to Disks"
52 depends on DASD && ARCH_S390X = 'n' 52 depends on DASD && ( ARCH_S390X = 'n' || EXPERIMENTAL)
53 help 53 help
54 Select this option if you want to use Diagnose250 command to access 54 Select this option if you want to use Diagnose250 command to access
55 Disks under VM. If you are not running under VM or unsure what it is, 55 Disks under VM. If you are not running under VM or unsure what it is,
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d5f53980749b..8fc891a9d47f 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,7 @@
7 * Bugreports.to..: <Linux390@de.ibm.com> 7 * Bugreports.to..: <Linux390@de.ibm.com>
8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
9 * 9 *
10 * $Revision: 1.165 $ 10 * $Revision: 1.167 $
11 */ 11 */
12 12
13#include <linux/config.h> 13#include <linux/config.h>
@@ -1131,17 +1131,13 @@ __dasd_process_blk_queue(struct dasd_device * device)
1131 request_queue_t *queue; 1131 request_queue_t *queue;
1132 struct request *req; 1132 struct request *req;
1133 struct dasd_ccw_req *cqr; 1133 struct dasd_ccw_req *cqr;
1134 int nr_queued, feature_ro; 1134 int nr_queued;
1135 1135
1136 queue = device->request_queue; 1136 queue = device->request_queue;
1137 /* No queue ? Then there is nothing to do. */ 1137 /* No queue ? Then there is nothing to do. */
1138 if (queue == NULL) 1138 if (queue == NULL)
1139 return; 1139 return;
1140 1140
1141 feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
1142 if (feature_ro < 0) /* no devmap */
1143 return;
1144
1145 /* 1141 /*
1146 * We requeue request from the block device queue to the ccw 1142 * We requeue request from the block device queue to the ccw
1147 * queue only in two states. In state DASD_STATE_READY the 1143 * queue only in two states. In state DASD_STATE_READY the
@@ -1162,7 +1158,8 @@ __dasd_process_blk_queue(struct dasd_device * device)
1162 nr_queued < DASD_CHANQ_MAX_SIZE) { 1158 nr_queued < DASD_CHANQ_MAX_SIZE) {
1163 req = elv_next_request(queue); 1159 req = elv_next_request(queue);
1164 1160
1165 if (feature_ro && rq_data_dir(req) == WRITE) { 1161 if (device->features & DASD_FEATURE_READONLY &&
1162 rq_data_dir(req) == WRITE) {
1166 DBF_DEV_EVENT(DBF_ERR, device, 1163 DBF_DEV_EVENT(DBF_ERR, device,
1167 "Rejecting write request %p", 1164 "Rejecting write request %p",
1168 req); 1165 req);
@@ -1814,17 +1811,13 @@ dasd_generic_set_online (struct ccw_device *cdev,
1814 1811
1815{ 1812{
1816 struct dasd_device *device; 1813 struct dasd_device *device;
1817 int feature_diag, rc; 1814 int rc;
1818 1815
1819 device = dasd_create_device(cdev); 1816 device = dasd_create_device(cdev);
1820 if (IS_ERR(device)) 1817 if (IS_ERR(device))
1821 return PTR_ERR(device); 1818 return PTR_ERR(device);
1822 1819
1823 feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG); 1820 if (device->features & DASD_FEATURE_USEDIAG) {
1824 if (feature_diag < 0)
1825 return feature_diag;
1826
1827 if (feature_diag) {
1828 if (!dasd_diag_discipline_pointer) { 1821 if (!dasd_diag_discipline_pointer) {
1829 printk (KERN_WARNING 1822 printk (KERN_WARNING
1830 "dasd_generic couldn't online device %s " 1823 "dasd_generic couldn't online device %s "
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index d948566bb24a..bda896d9d788 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -11,7 +11,7 @@
11 * functions may not be called from interrupt context. In particular 11 * functions may not be called from interrupt context. In particular
12 * dasd_get_device is a no-no from interrupt context. 12 * dasd_get_device is a no-no from interrupt context.
13 * 13 *
14 * $Revision: 1.40 $ 14 * $Revision: 1.43 $
15 */ 15 */
16 16
17#include <linux/config.h> 17#include <linux/config.h>
@@ -513,6 +513,7 @@ dasd_create_device(struct ccw_device *cdev)
513 if (!devmap->device) { 513 if (!devmap->device) {
514 devmap->device = device; 514 devmap->device = device;
515 device->devindex = devmap->devindex; 515 device->devindex = devmap->devindex;
516 device->features = devmap->features;
516 get_device(&cdev->dev); 517 get_device(&cdev->dev);
517 device->cdev = cdev; 518 device->cdev = cdev;
518 rc = 0; 519 rc = 0;
@@ -643,6 +644,8 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf
643 devmap->features |= DASD_FEATURE_READONLY; 644 devmap->features |= DASD_FEATURE_READONLY;
644 else 645 else
645 devmap->features &= ~DASD_FEATURE_READONLY; 646 devmap->features &= ~DASD_FEATURE_READONLY;
647 if (devmap->device)
648 devmap->device->features = devmap->features;
646 if (devmap->device && devmap->device->gdp) 649 if (devmap->device && devmap->device->gdp)
647 set_disk_ro(devmap->device->gdp, ro_flag); 650 set_disk_ro(devmap->device->gdp, ro_flag);
648 spin_unlock(&dasd_devmap_lock); 651 spin_unlock(&dasd_devmap_lock);
@@ -758,7 +761,8 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
758 devmap->features |= feature; 761 devmap->features |= feature;
759 else 762 else
760 devmap->features &= ~feature; 763 devmap->features &= ~feature;
761 764 if (devmap->device)
765 devmap->device->features = devmap->features;
762 spin_unlock(&dasd_devmap_lock); 766 spin_unlock(&dasd_devmap_lock);
763 return 0; 767 return 0;
764} 768}
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 127699830fa1..7478423b53bb 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,17 +6,18 @@
6 * Bugreports.to..: <Linux390@de.ibm.com> 6 * Bugreports.to..: <Linux390@de.ibm.com>
7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
8 * 8 *
9 * $Revision: 1.42 $ 9 * $Revision: 1.49 $
10 */ 10 */
11 11
12#include <linux/config.h> 12#include <linux/config.h>
13#include <linux/stddef.h> 13#include <linux/stddef.h>
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/hdreg.h> /* HDIO_GETGEO */ 16#include <linux/hdreg.h>
17#include <linux/bio.h> 17#include <linux/bio.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/jiffies.h>
20 21
21#include <asm/dasd.h> 22#include <asm/dasd.h>
22#include <asm/debug.h> 23#include <asm/debug.h>
@@ -28,58 +29,89 @@
28#include "dasd_int.h" 29#include "dasd_int.h"
29#include "dasd_diag.h" 30#include "dasd_diag.h"
30 31
31#ifdef PRINTK_HEADER
32#undef PRINTK_HEADER
33#endif /* PRINTK_HEADER */
34#define PRINTK_HEADER "dasd(diag):" 32#define PRINTK_HEADER "dasd(diag):"
35 33
36MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
37 35
36/* The maximum number of blocks per request (max_blocks) is dependent on the
37 * amount of storage that is available in the static I/O buffer for each
38 * device. Currently each device gets 2 pages. We want to fit two requests
39 * into the available memory so that we can immediately start the next if one
40 * finishes. */
41#define DIAG_MAX_BLOCKS (((2 * PAGE_SIZE - sizeof(struct dasd_ccw_req) - \
42 sizeof(struct dasd_diag_req)) / \
43 sizeof(struct dasd_diag_bio)) / 2)
44#define DIAG_MAX_RETRIES 32
45#define DIAG_TIMEOUT 50 * HZ
46
38struct dasd_discipline dasd_diag_discipline; 47struct dasd_discipline dasd_diag_discipline;
39 48
40struct dasd_diag_private { 49struct dasd_diag_private {
41 struct dasd_diag_characteristics rdc_data; 50 struct dasd_diag_characteristics rdc_data;
42 struct dasd_diag_rw_io iob; 51 struct dasd_diag_rw_io iob;
43 struct dasd_diag_init_io iib; 52 struct dasd_diag_init_io iib;
44 unsigned int pt_block; 53 blocknum_t pt_block;
45}; 54};
46 55
47struct dasd_diag_req { 56struct dasd_diag_req {
48 int block_count; 57 unsigned int block_count;
49 struct dasd_diag_bio bio[0]; 58 struct dasd_diag_bio bio[0];
50}; 59};
51 60
61static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
62
63/* Perform DIAG250 call with block I/O parameter list iob (input and output)
64 * and function code cmd.
65 * In case of an exception return 3. Otherwise return result of bitwise OR of
66 * resulting condition code and DIAG return code. */
52static __inline__ int 67static __inline__ int
53dia250(void *iob, int cmd) 68dia250(void *iob, int cmd)
54{ 69{
70 typedef struct {
71 char _[max(sizeof (struct dasd_diag_init_io),
72 sizeof (struct dasd_diag_rw_io))];
73 } addr_type;
55 int rc; 74 int rc;
56 75
57 __asm__ __volatile__(" lhi %0,3\n" 76 __asm__ __volatile__(
58 " lr 0,%2\n" 77#ifdef CONFIG_ARCH_S390X
59 " diag 0,%1,0x250\n" 78 " lghi %0,3\n"
60 "0: ipm %0\n" 79 " lgr 0,%3\n"
61 " srl %0,28\n" 80 " diag 0,%2,0x250\n"
62 " or %0,1\n" 81 "0: ipm %0\n"
63 "1:\n" 82 " srl %0,28\n"
64#ifndef CONFIG_ARCH_S390X 83 " or %0,1\n"
65 ".section __ex_table,\"a\"\n" 84 "1:\n"
66 " .align 4\n" 85 ".section __ex_table,\"a\"\n"
67 " .long 0b,1b\n" 86 " .align 8\n"
68 ".previous\n" 87 " .quad 0b,1b\n"
88 ".previous\n"
69#else 89#else
70 ".section __ex_table,\"a\"\n" 90 " lhi %0,3\n"
71 " .align 8\n" 91 " lr 0,%3\n"
72 " .quad 0b,1b\n" 92 " diag 0,%2,0x250\n"
73 ".previous\n" 93 "0: ipm %0\n"
94 " srl %0,28\n"
95 " or %0,1\n"
96 "1:\n"
97 ".section __ex_table,\"a\"\n"
98 " .align 4\n"
99 " .long 0b,1b\n"
100 ".previous\n"
74#endif 101#endif
75 : "=&d" (rc) 102 : "=&d" (rc), "=m" (*(addr_type *) iob)
76 : "d" (cmd), "d" ((void *) __pa(iob)) 103 : "d" (cmd), "d" (iob), "m" (*(addr_type *) iob)
77 : "0", "1", "cc"); 104 : "0", "1", "cc");
78 return rc; 105 return rc;
79} 106}
80 107
108/* Initialize block I/O to DIAG device using the specified blocksize and
109 * block offset. On success, return zero and set end_block to contain the
110 * number of blocks on the device minus the specified offset. Return non-zero
111 * otherwise. */
81static __inline__ int 112static __inline__ int
82mdsk_init_io(struct dasd_device * device, int blocksize, int offset, int size) 113mdsk_init_io(struct dasd_device *device, unsigned int blocksize,
114 blocknum_t offset, blocknum_t *end_block)
83{ 115{
84 struct dasd_diag_private *private; 116 struct dasd_diag_private *private;
85 struct dasd_diag_init_io *iib; 117 struct dasd_diag_init_io *iib;
@@ -92,14 +124,18 @@ mdsk_init_io(struct dasd_device * device, int blocksize, int offset, int size)
92 iib->dev_nr = _ccw_device_get_device_number(device->cdev); 124 iib->dev_nr = _ccw_device_get_device_number(device->cdev);
93 iib->block_size = blocksize; 125 iib->block_size = blocksize;
94 iib->offset = offset; 126 iib->offset = offset;
95 iib->start_block = 0; 127 iib->flaga = DASD_DIAG_FLAGA_DEFAULT;
96 iib->end_block = size;
97 128
98 rc = dia250(iib, INIT_BIO); 129 rc = dia250(iib, INIT_BIO);
99 130
100 return rc & 3; 131 if ((rc & 3) == 0 && end_block)
132 *end_block = iib->end_block;
133
134 return rc;
101} 135}
102 136
137/* Remove block I/O environment for device. Return zero on success, non-zero
138 * otherwise. */
103static __inline__ int 139static __inline__ int
104mdsk_term_io(struct dasd_device * device) 140mdsk_term_io(struct dasd_device * device)
105{ 141{
@@ -112,9 +148,25 @@ mdsk_term_io(struct dasd_device * device)
112 memset(iib, 0, sizeof (struct dasd_diag_init_io)); 148 memset(iib, 0, sizeof (struct dasd_diag_init_io));
113 iib->dev_nr = _ccw_device_get_device_number(device->cdev); 149 iib->dev_nr = _ccw_device_get_device_number(device->cdev);
114 rc = dia250(iib, TERM_BIO); 150 rc = dia250(iib, TERM_BIO);
115 return rc & 3; 151 return rc;
152}
153
154/* Error recovery for failed DIAG requests - try to reestablish the DIAG
155 * environment. */
156static void
157dasd_diag_erp(struct dasd_device *device)
158{
159 int rc;
160
161 mdsk_term_io(device);
162 rc = mdsk_init_io(device, device->bp_block, 0, NULL);
163 if (rc)
164 DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, "
165 "rc=%d", rc);
116} 166}
117 167
168/* Start a given request at the device. Return zero on success, non-zero
169 * otherwise. */
118static int 170static int
119dasd_start_diag(struct dasd_ccw_req * cqr) 171dasd_start_diag(struct dasd_ccw_req * cqr)
120{ 172{
@@ -124,32 +176,66 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
124 int rc; 176 int rc;
125 177
126 device = cqr->device; 178 device = cqr->device;
179 if (cqr->retries < 0) {
180 DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p "
181 "- no retry left)", cqr);
182 cqr->status = DASD_CQR_FAILED;
183 return -EIO;
184 }
127 private = (struct dasd_diag_private *) device->private; 185 private = (struct dasd_diag_private *) device->private;
128 dreq = (struct dasd_diag_req *) cqr->data; 186 dreq = (struct dasd_diag_req *) cqr->data;
129 187
130 private->iob.dev_nr = _ccw_device_get_device_number(device->cdev); 188 private->iob.dev_nr = _ccw_device_get_device_number(device->cdev);
131 private->iob.key = 0; 189 private->iob.key = 0;
132 private->iob.flags = 2; /* do asynchronous io */ 190 private->iob.flags = DASD_DIAG_RWFLAG_ASYNC;
133 private->iob.block_count = dreq->block_count; 191 private->iob.block_count = dreq->block_count;
134 private->iob.interrupt_params = (u32)(addr_t) cqr; 192 private->iob.interrupt_params = (addr_t) cqr;
135 private->iob.bio_list = __pa(dreq->bio); 193 private->iob.bio_list = __pa(dreq->bio);
194 private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
136 195
137 cqr->startclk = get_clock(); 196 cqr->startclk = get_clock();
197 cqr->starttime = jiffies;
198 cqr->retries--;
138 199
139 rc = dia250(&private->iob, RW_BIO); 200 rc = dia250(&private->iob, RW_BIO);
140 if (rc > 8) { 201 switch (rc) {
141 DEV_MESSAGE(KERN_WARNING, device, "dia250 returned CC %d", rc); 202 case 0: /* Synchronous I/O finished successfully */
142 cqr->status = DASD_CQR_ERROR; 203 cqr->stopclk = get_clock();
143 } else if (rc == 0) {
144 cqr->status = DASD_CQR_DONE; 204 cqr->status = DASD_CQR_DONE;
145 dasd_schedule_bh(device); 205 /* Indicate to calling function that only a dasd_schedule_bh()
146 } else { 206 and no timer is needed */
207 rc = -EACCES;
208 break;
209 case 8: /* Asynchronous I/O was started */
147 cqr->status = DASD_CQR_IN_IO; 210 cqr->status = DASD_CQR_IN_IO;
148 rc = 0; 211 rc = 0;
212 break;
213 default: /* Error condition */
214 cqr->status = DASD_CQR_QUEUED;
215 DEV_MESSAGE(KERN_WARNING, device, "dia250 returned rc=%d", rc);
216 dasd_diag_erp(device);
217 rc = -EIO;
218 break;
149 } 219 }
150 return rc; 220 return rc;
151} 221}
152 222
223/* Terminate given request at the device. */
224static int
225dasd_diag_term_IO(struct dasd_ccw_req * cqr)
226{
227 struct dasd_device *device;
228
229 device = cqr->device;
230 mdsk_term_io(device);
231 mdsk_init_io(device, device->bp_block, 0, NULL);
232 cqr->status = DASD_CQR_CLEAR;
233 cqr->stopclk = get_clock();
234 dasd_schedule_bh(device);
235 return 0;
236}
237
238/* Handle external interruption. */
153static void 239static void
154dasd_ext_handler(struct pt_regs *regs, __u16 code) 240dasd_ext_handler(struct pt_regs *regs, __u16 code)
155{ 241{
@@ -157,25 +243,27 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
157 struct dasd_device *device; 243 struct dasd_device *device;
158 unsigned long long expires; 244 unsigned long long expires;
159 unsigned long flags; 245 unsigned long flags;
160 char status; 246 u8 int_code, status;
161 int ip; 247 addr_t ip;
162 248 int rc;
163 /*
164 * Get the external interruption subcode. VM stores
165 * this in the 'cpu address' field associated with
166 * the external interrupt. For diag 250 the subcode
167 * needs to be 3.
168 */
169 if ((S390_lowcore.cpu_addr & 0xff00) != 0x0300)
170 return;
171 status = *((char *) &S390_lowcore.ext_params + 5);
172 ip = S390_lowcore.ext_params;
173 249
250 int_code = *((u8 *) DASD_DIAG_LC_INT_CODE);
251 status = *((u8 *) DASD_DIAG_LC_INT_STATUS);
252 switch (int_code) {
253 case DASD_DIAG_CODE_31BIT:
254 ip = (addr_t) *((u32 *) DASD_DIAG_LC_INT_PARM_31BIT);
255 break;
256 case DASD_DIAG_CODE_64BIT:
257 ip = (addr_t) *((u64 *) DASD_DIAG_LC_INT_PARM_64BIT);
258 break;
259 default:
260 return;
261 }
174 if (!ip) { /* no intparm: unsolicited interrupt */ 262 if (!ip) { /* no intparm: unsolicited interrupt */
175 MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt"); 263 MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt");
176 return; 264 return;
177 } 265 }
178 cqr = (struct dasd_ccw_req *)(addr_t) ip; 266 cqr = (struct dasd_ccw_req *) ip;
179 device = (struct dasd_device *) cqr->device; 267 device = (struct dasd_device *) cqr->device;
180 if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { 268 if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
181 DEV_MESSAGE(KERN_WARNING, device, 269 DEV_MESSAGE(KERN_WARNING, device,
@@ -188,6 +276,15 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
188 /* get irq lock to modify request queue */ 276 /* get irq lock to modify request queue */
189 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); 277 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
190 278
279 /* Check for a pending clear operation */
280 if (cqr->status == DASD_CQR_CLEAR) {
281 cqr->status = DASD_CQR_QUEUED;
282 dasd_clear_timer(device);
283 dasd_schedule_bh(device);
284 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
285 return;
286 }
287
191 cqr->stopclk = get_clock(); 288 cqr->stopclk = get_clock();
192 289
193 expires = 0; 290 expires = 0;
@@ -198,16 +295,22 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
198 next = list_entry(device->ccw_queue.next, 295 next = list_entry(device->ccw_queue.next,
199 struct dasd_ccw_req, list); 296 struct dasd_ccw_req, list);
200 if (next->status == DASD_CQR_QUEUED) { 297 if (next->status == DASD_CQR_QUEUED) {
201 if (dasd_start_diag(next) == 0) 298 rc = dasd_start_diag(next);
299 if (rc == 0)
202 expires = next->expires; 300 expires = next->expires;
203 else 301 else if (rc != -EACCES)
204 DEV_MESSAGE(KERN_WARNING, device, "%s", 302 DEV_MESSAGE(KERN_WARNING, device, "%s",
205 "Interrupt fastpath " 303 "Interrupt fastpath "
206 "failed!"); 304 "failed!");
207 } 305 }
208 } 306 }
209 } else 307 } else {
210 cqr->status = DASD_CQR_FAILED; 308 cqr->status = DASD_CQR_QUEUED;
309 DEV_MESSAGE(KERN_WARNING, device, "interrupt status for "
310 "request %p was %d (%d retries left)", cqr, status,
311 cqr->retries);
312 dasd_diag_erp(device);
313 }
211 314
212 if (expires != 0) 315 if (expires != 0)
213 dasd_set_timer(device, expires); 316 dasd_set_timer(device, expires);
@@ -218,14 +321,17 @@ dasd_ext_handler(struct pt_regs *regs, __u16 code)
218 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); 321 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
219} 322}
220 323
324/* Check whether device can be controlled by DIAG discipline. Return zero on
325 * success, non-zero otherwise. */
221static int 326static int
222dasd_diag_check_device(struct dasd_device *device) 327dasd_diag_check_device(struct dasd_device *device)
223{ 328{
224 struct dasd_diag_private *private; 329 struct dasd_diag_private *private;
225 struct dasd_diag_characteristics *rdc_data; 330 struct dasd_diag_characteristics *rdc_data;
226 struct dasd_diag_bio bio; 331 struct dasd_diag_bio bio;
227 long *label; 332 struct dasd_diag_cms_label *label;
228 int sb, bsize; 333 blocknum_t end_block;
334 unsigned int sb, bsize;
229 int rc; 335 int rc;
230 336
231 private = (struct dasd_diag_private *) device->private; 337 private = (struct dasd_diag_private *) device->private;
@@ -244,8 +350,11 @@ dasd_diag_check_device(struct dasd_device *device)
244 rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics); 350 rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics);
245 351
246 rc = diag210((struct diag210 *) rdc_data); 352 rc = diag210((struct diag210 *) rdc_data);
247 if (rc) 353 if (rc) {
354 DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device "
355 "information (rc=%d)", rc);
248 return -ENOTSUPP; 356 return -ENOTSUPP;
357 }
249 358
250 /* Figure out position of label block */ 359 /* Figure out position of label block */
251 switch (private->rdc_data.vdev_class) { 360 switch (private->rdc_data.vdev_class) {
@@ -256,6 +365,8 @@ dasd_diag_check_device(struct dasd_device *device)
256 private->pt_block = 2; 365 private->pt_block = 2;
257 break; 366 break;
258 default: 367 default:
368 DEV_MESSAGE(KERN_WARNING, device, "unsupported device class "
369 "(class=%d)", private->rdc_data.vdev_class);
259 return -ENOTSUPP; 370 return -ENOTSUPP;
260 } 371 }
261 372
@@ -269,15 +380,17 @@ dasd_diag_check_device(struct dasd_device *device)
269 mdsk_term_io(device); 380 mdsk_term_io(device);
270 381
271 /* figure out blocksize of device */ 382 /* figure out blocksize of device */
272 label = (long *) get_zeroed_page(GFP_KERNEL); 383 label = (struct dasd_diag_cms_label *) get_zeroed_page(GFP_KERNEL);
273 if (label == NULL) { 384 if (label == NULL) {
274 DEV_MESSAGE(KERN_WARNING, device, "%s", 385 DEV_MESSAGE(KERN_WARNING, device, "%s",
275 "No memory to allocate initialization request"); 386 "No memory to allocate initialization request");
276 return -ENOMEM; 387 return -ENOMEM;
277 } 388 }
389 rc = 0;
390 end_block = 0;
278 /* try all sizes - needed for ECKD devices */ 391 /* try all sizes - needed for ECKD devices */
279 for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) { 392 for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) {
280 mdsk_init_io(device, bsize, 0, 64); 393 mdsk_init_io(device, bsize, 0, &end_block);
281 memset(&bio, 0, sizeof (struct dasd_diag_bio)); 394 memset(&bio, 0, sizeof (struct dasd_diag_bio));
282 bio.type = MDSK_READ_REQ; 395 bio.type = MDSK_READ_REQ;
283 bio.block_number = private->pt_block + 1; 396 bio.block_number = private->pt_block + 1;
@@ -289,37 +402,45 @@ dasd_diag_check_device(struct dasd_device *device)
289 private->iob.block_count = 1; 402 private->iob.block_count = 1;
290 private->iob.interrupt_params = 0; 403 private->iob.interrupt_params = 0;
291 private->iob.bio_list = __pa(&bio); 404 private->iob.bio_list = __pa(&bio);
292 if (dia250(&private->iob, RW_BIO) == 0) 405 private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
406 rc = dia250(&private->iob, RW_BIO);
407 if (rc == 0 || rc == 3)
293 break; 408 break;
294 mdsk_term_io(device); 409 mdsk_term_io(device);
295 } 410 }
296 if (bsize <= PAGE_SIZE && label[0] == 0xc3d4e2f1) { 411 if (rc == 3) {
297 /* get formatted blocksize from label block */ 412 DEV_MESSAGE(KERN_WARNING, device, "%s", "DIAG call failed");
298 bsize = (int) label[3]; 413 rc = -EOPNOTSUPP;
299 device->blocks = label[7]; 414 } else if (rc != 0) {
415 DEV_MESSAGE(KERN_WARNING, device, "device access failed "
416 "(rc=%d)", rc);
417 rc = -EIO;
418 } else {
419 if (memcmp(label->label_id, DASD_DIAG_CMS1,
420 sizeof(DASD_DIAG_CMS1)) == 0) {
421 /* get formatted blocksize from label block */
422 bsize = (unsigned int) label->block_size;
423 device->blocks = (unsigned long) label->block_count;
424 } else
425 device->blocks = end_block;
300 device->bp_block = bsize; 426 device->bp_block = bsize;
301 device->s2b_shift = 0; /* bits to shift 512 to get a block */ 427 device->s2b_shift = 0; /* bits to shift 512 to get a block */
302 for (sb = 512; sb < bsize; sb = sb << 1) 428 for (sb = 512; sb < bsize; sb = sb << 1)
303 device->s2b_shift++; 429 device->s2b_shift++;
304 430
305 DEV_MESSAGE(KERN_INFO, device, 431 DEV_MESSAGE(KERN_INFO, device,
306 "capacity (%dkB blks): %ldkB", 432 "(%ld B/blk): %ldkB",
307 (device->bp_block >> 10), 433 (unsigned long) device->bp_block,
308 (device->blocks << device->s2b_shift) >> 1); 434 (unsigned long) (device->blocks <<
435 device->s2b_shift) >> 1);
309 rc = 0; 436 rc = 0;
310 } else {
311 if (bsize > PAGE_SIZE)
312 DEV_MESSAGE(KERN_WARNING, device, "%s",
313 "DIAG access failed");
314 else
315 DEV_MESSAGE(KERN_WARNING, device, "%s",
316 "volume is not CMS formatted");
317 rc = -EMEDIUMTYPE;
318 } 437 }
319 free_page((long) label); 438 free_page((long) label);
320 return rc; 439 return rc;
321} 440}
322 441
442/* Fill in virtual disk geometry for device. Return zero on success, non-zero
443 * otherwise. */
323static int 444static int
324dasd_diag_fill_geometry(struct dasd_device *device, struct hd_geometry *geo) 445dasd_diag_fill_geometry(struct dasd_device *device, struct hd_geometry *geo)
325{ 446{
@@ -349,6 +470,8 @@ dasd_diag_erp_postaction(struct dasd_ccw_req * cqr)
349 return dasd_default_erp_postaction; 470 return dasd_default_erp_postaction;
350} 471}
351 472
473/* Create DASD request from block device request. Return pointer to new
474 * request on success, ERR_PTR otherwise. */
352static struct dasd_ccw_req * 475static struct dasd_ccw_req *
353dasd_diag_build_cp(struct dasd_device * device, struct request *req) 476dasd_diag_build_cp(struct dasd_device * device, struct request *req)
354{ 477{
@@ -358,9 +481,9 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
358 struct bio *bio; 481 struct bio *bio;
359 struct bio_vec *bv; 482 struct bio_vec *bv;
360 char *dst; 483 char *dst;
361 int count, datasize; 484 unsigned int count, datasize;
362 sector_t recid, first_rec, last_rec; 485 sector_t recid, first_rec, last_rec;
363 unsigned blksize, off; 486 unsigned int blksize, off;
364 unsigned char rw_cmd; 487 unsigned char rw_cmd;
365 int i; 488 int i;
366 489
@@ -413,13 +536,16 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
413 } 536 }
414 } 537 }
415 } 538 }
539 cqr->retries = DIAG_MAX_RETRIES;
416 cqr->buildclk = get_clock(); 540 cqr->buildclk = get_clock();
417 cqr->device = device; 541 cqr->device = device;
418 cqr->expires = 50 * HZ; /* 50 seconds */ 542 cqr->expires = DIAG_TIMEOUT;
419 cqr->status = DASD_CQR_FILLED; 543 cqr->status = DASD_CQR_FILLED;
420 return cqr; 544 return cqr;
421} 545}
422 546
547/* Release DASD request. Return non-zero if request was successful, zero
548 * otherwise. */
423static int 549static int
424dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req) 550dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req)
425{ 551{
@@ -430,6 +556,7 @@ dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req)
430 return status; 556 return status;
431} 557}
432 558
559/* Fill in IOCTL data for device. */
433static int 560static int
434dasd_diag_fill_info(struct dasd_device * device, 561dasd_diag_fill_info(struct dasd_device * device,
435 struct dasd_information2_t * info) 562 struct dasd_information2_t * info)
@@ -437,7 +564,7 @@ dasd_diag_fill_info(struct dasd_device * device,
437 struct dasd_diag_private *private; 564 struct dasd_diag_private *private;
438 565
439 private = (struct dasd_diag_private *) device->private; 566 private = (struct dasd_diag_private *) device->private;
440 info->label_block = private->pt_block; 567 info->label_block = (unsigned int) private->pt_block;
441 info->FBA_layout = 1; 568 info->FBA_layout = 1;
442 info->format = DASD_FORMAT_LDL; 569 info->format = DASD_FORMAT_LDL;
443 info->characteristics_size = sizeof (struct dasd_diag_characteristics); 570 info->characteristics_size = sizeof (struct dasd_diag_characteristics);
@@ -456,26 +583,15 @@ dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
456 "dump sense not available for DIAG data"); 583 "dump sense not available for DIAG data");
457} 584}
458 585
459/*
460 * max_blocks is dependent on the amount of storage that is available
461 * in the static io buffer for each device. Currently each device has
462 * 8192 bytes (=2 pages). dasd diag is only relevant for 31 bit.
463 * The struct dasd_ccw_req has 96 bytes, the struct dasd_diag_req has
464 * 8 bytes and the struct dasd_diag_bio for each block has 16 bytes.
465 * That makes:
466 * (8192 - 96 - 8) / 16 = 505.5 blocks at maximum.
467 * We want to fit two into the available memory so that we can immediately
468 * start the next request if one finishes off. That makes 252.75 blocks
469 * for one request. Give a little safety and the result is 240.
470 */
471struct dasd_discipline dasd_diag_discipline = { 586struct dasd_discipline dasd_diag_discipline = {
472 .owner = THIS_MODULE, 587 .owner = THIS_MODULE,
473 .name = "DIAG", 588 .name = "DIAG",
474 .ebcname = "DIAG", 589 .ebcname = "DIAG",
475 .max_blocks = 240, 590 .max_blocks = DIAG_MAX_BLOCKS,
476 .check_device = dasd_diag_check_device, 591 .check_device = dasd_diag_check_device,
477 .fill_geometry = dasd_diag_fill_geometry, 592 .fill_geometry = dasd_diag_fill_geometry,
478 .start_IO = dasd_start_diag, 593 .start_IO = dasd_start_diag,
594 .term_IO = dasd_diag_term_IO,
479 .examine_error = dasd_diag_examine_error, 595 .examine_error = dasd_diag_examine_error,
480 .erp_action = dasd_diag_erp_action, 596 .erp_action = dasd_diag_erp_action,
481 .erp_postaction = dasd_diag_erp_postaction, 597 .erp_postaction = dasd_diag_erp_postaction,
@@ -493,7 +609,7 @@ dasd_diag_init(void)
493 "Machine is not VM: %s " 609 "Machine is not VM: %s "
494 "discipline not initializing", 610 "discipline not initializing",
495 dasd_diag_discipline.name); 611 dasd_diag_discipline.name);
496 return -EINVAL; 612 return -ENODEV;
497 } 613 }
498 ASCEBC(dasd_diag_discipline.ebcname, 4); 614 ASCEBC(dasd_diag_discipline.ebcname, 4);
499 615
@@ -506,13 +622,6 @@ dasd_diag_init(void)
506static void __exit 622static void __exit
507dasd_diag_cleanup(void) 623dasd_diag_cleanup(void)
508{ 624{
509 if (!MACHINE_IS_VM) {
510 MESSAGE_LOG(KERN_INFO,
511 "Machine is not VM: %s "
512 "discipline not cleaned",
513 dasd_diag_discipline.name);
514 return;
515 }
516 unregister_external_interrupt(0x2603, dasd_ext_handler); 625 unregister_external_interrupt(0x2603, dasd_ext_handler);
517 ctl_clear_bit(0, 9); 626 ctl_clear_bit(0, 9);
518 dasd_diag_discipline_pointer = NULL; 627 dasd_diag_discipline_pointer = NULL;
@@ -520,22 +629,3 @@ dasd_diag_cleanup(void)
520 629
521module_init(dasd_diag_init); 630module_init(dasd_diag_init);
522module_exit(dasd_diag_cleanup); 631module_exit(dasd_diag_cleanup);
523
524/*
525 * Overrides for Emacs so that we follow Linus's tabbing style.
526 * Emacs will notice this stuff at the end of the file and automatically
527 * adjust the settings for this buffer only. This must remain at the end
528 * of the file.
529 * ---------------------------------------------------------------------------
530 * Local variables:
531 * c-indent-level: 4
532 * c-brace-imaginary-offset: 0
533 * c-brace-offset: -4
534 * c-argdecl-indent: 4
535 * c-label-offset: -4
536 * c-continued-statement-offset: 4
537 * c-continued-brace-offset: 0
538 * indent-tabs-mode: 1
539 * tab-width: 8
540 * End:
541 */
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h
index a0c38e303979..b26eb28df4bf 100644
--- a/drivers/s390/block/dasd_diag.h
+++ b/drivers/s390/block/dasd_diag.h
@@ -6,7 +6,7 @@
6 * Bugreports.to..: <Linux390@de.ibm.com> 6 * Bugreports.to..: <Linux390@de.ibm.com>
7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
8 * 8 *
9 * $Revision: 1.6 $ 9 * $Revision: 1.7 $
10 */ 10 */
11 11
12#define MDSK_WRITE_REQ 0x01 12#define MDSK_WRITE_REQ 0x01
@@ -19,6 +19,18 @@
19#define DEV_CLASS_FBA 0x01 19#define DEV_CLASS_FBA 0x01
20#define DEV_CLASS_ECKD 0x04 20#define DEV_CLASS_ECKD 0x04
21 21
22#define DASD_DIAG_LC_INT_CODE 132
23#define DASD_DIAG_LC_INT_STATUS 133
24#define DASD_DIAG_LC_INT_PARM_31BIT 128
25#define DASD_DIAG_LC_INT_PARM_64BIT 4536
26#define DASD_DIAG_CODE_31BIT 0x03
27#define DASD_DIAG_CODE_64BIT 0x07
28
29#define DASD_DIAG_RWFLAG_ASYNC 0x02
30#define DASD_DIAG_RWFLAG_NOCACHE 0x01
31
32#define DASD_DIAG_FLAGA_FORMAT_64BIT 0x80
33
22struct dasd_diag_characteristics { 34struct dasd_diag_characteristics {
23 u16 dev_nr; 35 u16 dev_nr;
24 u16 rdc_len; 36 u16 rdc_len;
@@ -32,35 +44,106 @@ struct dasd_diag_characteristics {
32 u8 rdev_features; 44 u8 rdev_features;
33} __attribute__ ((packed, aligned(4))); 45} __attribute__ ((packed, aligned(4)));
34 46
47struct dasd_diag_cms_label {
48 u8 label_id[4];
49 u8 vol_id[6];
50 u16 version_id;
51 u32 block_size;
52 u32 origin_ptr;
53 u32 usable_count;
54 u32 formatted_count;
55 u32 block_count;
56 u32 used_count;
57 u32 fst_size;
58 u32 fst_count;
59 u8 format_date[6];
60 u8 reserved1[2];
61 u32 disk_offset;
62 u32 map_block;
63 u32 hblk_disp;
64 u32 user_disp;
65 u8 reserved2[4];
66 u8 segment_name[8];
67} __attribute__ ((packed));
68
69#ifdef CONFIG_ARCH_S390X
70#define DASD_DIAG_FLAGA_DEFAULT DASD_DIAG_FLAGA_FORMAT_64BIT
71
72typedef u64 blocknum_t;
73typedef s64 sblocknum_t;
74
75struct dasd_diag_bio {
76 u8 type;
77 u8 status;
78 u8 spare1[2];
79 u32 alet;
80 blocknum_t block_number;
81 u64 buffer;
82} __attribute__ ((packed, aligned(8)));
83
84struct dasd_diag_init_io {
85 u16 dev_nr;
86 u8 flaga;
87 u8 spare1[21];
88 u32 block_size;
89 u8 spare2[4];
90 blocknum_t offset;
91 sblocknum_t start_block;
92 blocknum_t end_block;
93 u8 spare3[8];
94} __attribute__ ((packed, aligned(8)));
95
96struct dasd_diag_rw_io {
97 u16 dev_nr;
98 u8 flaga;
99 u8 spare1[21];
100 u8 key;
101 u8 flags;
102 u8 spare2[2];
103 u32 block_count;
104 u32 alet;
105 u8 spare3[4];
106 u64 interrupt_params;
107 u64 bio_list;
108 u8 spare4[8];
109} __attribute__ ((packed, aligned(8)));
110#else /* CONFIG_ARCH_S390X */
111#define DASD_DIAG_FLAGA_DEFAULT 0x0
112
113typedef u32 blocknum_t;
114typedef s32 sblocknum_t;
115
35struct dasd_diag_bio { 116struct dasd_diag_bio {
36 u8 type; 117 u8 type;
37 u8 status; 118 u8 status;
38 u16 spare1; 119 u16 spare1;
39 u32 block_number; 120 blocknum_t block_number;
40 u32 alet; 121 u32 alet;
41 u32 buffer; 122 u32 buffer;
42} __attribute__ ((packed, aligned(8))); 123} __attribute__ ((packed, aligned(8)));
43 124
44struct dasd_diag_init_io { 125struct dasd_diag_init_io {
45 u16 dev_nr; 126 u16 dev_nr;
46 u16 spare1[11]; 127 u8 flaga;
128 u8 spare1[21];
47 u32 block_size; 129 u32 block_size;
48 u32 offset; 130 blocknum_t offset;
49 u32 start_block; 131 sblocknum_t start_block;
50 u32 end_block; 132 blocknum_t end_block;
51 u32 spare2[6]; 133 u8 spare2[24];
52} __attribute__ ((packed, aligned(8))); 134} __attribute__ ((packed, aligned(8)));
53 135
54struct dasd_diag_rw_io { 136struct dasd_diag_rw_io {
55 u16 dev_nr; 137 u16 dev_nr;
56 u16 spare1[11]; 138 u8 flaga;
139 u8 spare1[21];
57 u8 key; 140 u8 key;
58 u8 flags; 141 u8 flags;
59 u16 spare2; 142 u8 spare2[2];
60 u32 block_count; 143 u32 block_count;
61 u32 alet; 144 u32 alet;
62 u32 bio_list; 145 u32 bio_list;
63 u32 interrupt_params; 146 u32 interrupt_params;
64 u32 spare3[5]; 147 u8 spare3[20];
65} __attribute__ ((packed, aligned(8))); 148} __attribute__ ((packed, aligned(8)));
66 149#endif /* CONFIG_ARCH_S390X */
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 96c49349701f..a601c9a33541 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -9,7 +9,7 @@
9 * 9 *
10 * gendisk related functions for the dasd driver. 10 * gendisk related functions for the dasd driver.
11 * 11 *
12 * $Revision: 1.50 $ 12 * $Revision: 1.51 $
13 */ 13 */
14 14
15#include <linux/config.h> 15#include <linux/config.h>
@@ -31,16 +31,12 @@ int
31dasd_gendisk_alloc(struct dasd_device *device) 31dasd_gendisk_alloc(struct dasd_device *device)
32{ 32{
33 struct gendisk *gdp; 33 struct gendisk *gdp;
34 int len, feature_ro; 34 int len;
35 35
36 /* Make sure the minor for this device exists. */ 36 /* Make sure the minor for this device exists. */
37 if (device->devindex >= DASD_PER_MAJOR) 37 if (device->devindex >= DASD_PER_MAJOR)
38 return -EBUSY; 38 return -EBUSY;
39 39
40 feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
41 if (feature_ro < 0)
42 return feature_ro;
43
44 gdp = alloc_disk(1 << DASD_PARTN_BITS); 40 gdp = alloc_disk(1 << DASD_PARTN_BITS);
45 if (!gdp) 41 if (!gdp)
46 return -ENOMEM; 42 return -ENOMEM;
@@ -75,7 +71,7 @@ dasd_gendisk_alloc(struct dasd_device *device)
75 71
76 sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id); 72 sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id);
77 73
78 if (feature_ro) 74 if (device->features & DASD_FEATURE_READONLY)
79 set_disk_ro(gdp, 1); 75 set_disk_ro(gdp, 1);
80 gdp->private_data = device; 76 gdp->private_data = device;
81 gdp->queue = device->request_queue; 77 gdp->queue = device->request_queue;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index a9f38b235981..9fab04f3056d 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -6,7 +6,7 @@
6 * Bugreports.to..: <Linux390@de.ibm.com> 6 * Bugreports.to..: <Linux390@de.ibm.com>
7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
8 * 8 *
9 * $Revision: 1.64 $ 9 * $Revision: 1.65 $
10 */ 10 */
11 11
12#ifndef DASD_INT_H 12#ifndef DASD_INT_H
@@ -286,6 +286,7 @@ struct dasd_device {
286 unsigned int bp_block; /* bytes per block */ 286 unsigned int bp_block; /* bytes per block */
287 unsigned int s2b_shift; /* log2 (bp_block/512) */ 287 unsigned int s2b_shift; /* log2 (bp_block/512) */
288 unsigned long flags; /* per device flags */ 288 unsigned long flags; /* per device flags */
289 unsigned short features; /* copy of devmap-features (read-only!) */
289 290
290 /* Device discipline stuff. */ 291 /* Device discipline stuff. */
291 struct dasd_discipline *discipline; 292 struct dasd_discipline *discipline;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 980c555aa538..789595b3fa09 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -7,7 +7,7 @@
7 * Bugreports.to..: <Linux390@de.ibm.com> 7 * Bugreports.to..: <Linux390@de.ibm.com>
8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
9 * 9 *
10 * $Revision: 1.45 $ 10 * $Revision: 1.47 $
11 * 11 *
12 * i/o controls for the dasd driver. 12 * i/o controls for the dasd driver.
13 */ 13 */
@@ -296,7 +296,6 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
296{ 296{
297 struct dasd_device *device; 297 struct dasd_device *device;
298 struct format_data_t fdata; 298 struct format_data_t fdata;
299 int feature_ro;
300 299
301 if (!capable(CAP_SYS_ADMIN)) 300 if (!capable(CAP_SYS_ADMIN))
302 return -EACCES; 301 return -EACCES;
@@ -308,10 +307,7 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
308 if (device == NULL) 307 if (device == NULL)
309 return -ENODEV; 308 return -ENODEV;
310 309
311 feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY); 310 if (device->features & DASD_FEATURE_READONLY)
312 if (feature_ro < 0)
313 return feature_ro;
314 if (feature_ro)
315 return -EROFS; 311 return -EROFS;
316 if (copy_from_user(&fdata, (void __user *) args, 312 if (copy_from_user(&fdata, (void __user *) args,
317 sizeof (struct format_data_t))) 313 sizeof (struct format_data_t)))
@@ -384,7 +380,7 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
384 struct dasd_device *device; 380 struct dasd_device *device;
385 struct dasd_information2_t *dasd_info; 381 struct dasd_information2_t *dasd_info;
386 unsigned long flags; 382 unsigned long flags;
387 int rc, feature_ro; 383 int rc;
388 struct ccw_device *cdev; 384 struct ccw_device *cdev;
389 385
390 device = bdev->bd_disk->private_data; 386 device = bdev->bd_disk->private_data;
@@ -394,10 +390,6 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
394 if (!device->discipline->fill_info) 390 if (!device->discipline->fill_info)
395 return -EINVAL; 391 return -EINVAL;
396 392
397 feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
398 if (feature_ro < 0)
399 return feature_ro;
400
401 dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL); 393 dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
402 if (dasd_info == NULL) 394 if (dasd_info == NULL)
403 return -ENOMEM; 395 return -ENOMEM;
@@ -427,7 +419,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
427 (dasd_check_blocksize(device->bp_block))) 419 (dasd_check_blocksize(device->bp_block)))
428 dasd_info->format = DASD_FORMAT_NONE; 420 dasd_info->format = DASD_FORMAT_NONE;
429 421
430 dasd_info->features |= feature_ro; 422 dasd_info->features |=
423 ((device->features & DASD_FEATURE_READONLY) != 0);
431 424
432 if (device->discipline) 425 if (device->discipline)
433 memcpy(dasd_info->type, device->discipline->name, 4); 426 memcpy(dasd_info->type, device->discipline->name, 4);
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 43c34f8c5e68..fff9020d4886 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -9,7 +9,7 @@
9 * 9 *
10 * /proc interface for the dasd driver. 10 * /proc interface for the dasd driver.
11 * 11 *
12 * $Revision: 1.32 $ 12 * $Revision: 1.33 $
13 */ 13 */
14 14
15#include <linux/config.h> 15#include <linux/config.h>
@@ -55,7 +55,6 @@ dasd_devices_show(struct seq_file *m, void *v)
55{ 55{
56 struct dasd_device *device; 56 struct dasd_device *device;
57 char *substr; 57 char *substr;
58 int feature;
59 58
60 device = dasd_device_from_devindex((unsigned long) v - 1); 59 device = dasd_device_from_devindex((unsigned long) v - 1);
61 if (IS_ERR(device)) 60 if (IS_ERR(device))
@@ -79,10 +78,7 @@ dasd_devices_show(struct seq_file *m, void *v)
79 else 78 else
80 seq_printf(m, " is ????????"); 79 seq_printf(m, " is ????????");
81 /* Print devices features. */ 80 /* Print devices features. */
82 feature = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY); 81 substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
83 if (feature < 0)
84 return 0;
85 substr = feature ? "(ro)" : " ";
86 seq_printf(m, "%4s: ", substr); 82 seq_printf(m, "%4s: ", substr);
87 /* Print device status information. */ 83 /* Print device status information. */
88 switch ((device != NULL) ? device->state : -1) { 84 switch ((device != NULL) ? device->state : -1) {
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index d5eefeaba50c..328d9cbc56a3 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -632,12 +632,9 @@ __raw3270_size_device(struct raw3270 *rp)
632 raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data); 632 raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);
633 633
634 rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request); 634 rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);
635 if (rc) { 635 if (rc)
636 /* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */ 636 /* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */
637 if (rc == -EOPNOTSUPP && MACHINE_IS_VM)
638 return __raw3270_size_device_vm(rp);
639 return rc; 637 return rc;
640 }
641 638
642 /* Wait for attention interrupt. */ 639 /* Wait for attention interrupt. */
643#ifdef CONFIG_TN3270_CONSOLE 640#ifdef CONFIG_TN3270_CONSOLE
@@ -695,7 +692,10 @@ raw3270_size_device(struct raw3270 *rp)
695 down(&raw3270_init_sem); 692 down(&raw3270_init_sem);
696 rp->view = &raw3270_init_view; 693 rp->view = &raw3270_init_view;
697 raw3270_init_view.dev = rp; 694 raw3270_init_view.dev = rp;
698 rc = __raw3270_size_device(rp); 695 if (MACHINE_IS_VM)
696 rc = __raw3270_size_device_vm(rp);
697 else
698 rc = __raw3270_size_device(rp);
699 raw3270_init_view.dev = 0; 699 raw3270_init_view.dev = 0;
700 rp->view = 0; 700 rp->view = 0;
701 up(&raw3270_init_sem); 701 up(&raw3270_init_sem);
@@ -710,6 +710,12 @@ raw3270_size_device(struct raw3270 *rp)
710 rp->model = 4; 710 rp->model = 4;
711 if (rp->rows == 27 && rp->cols == 132) 711 if (rp->rows == 27 && rp->cols == 132)
712 rp->model = 5; 712 rp->model = 5;
713 } else {
714 /* Couldn't detect size. Use default model 2. */
715 rp->model = 2;
716 rp->rows = 24;
717 rp->cols = 80;
718 return 0;
713 } 719 }
714 return rc; 720 return rc;
715} 721}
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index ea813bdce1d6..185bc73c3ecd 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/s390/cio/cio.c 2 * drivers/s390/cio/cio.c
3 * S/390 common I/O routines -- low level i/o calls 3 * S/390 common I/O routines -- low level i/o calls
4 * $Revision: 1.134 $ 4 * $Revision: 1.135 $
5 * 5 *
6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
@@ -815,8 +815,9 @@ __clear_subchannel_easy(unsigned int schid)
815 struct tpi_info ti; 815 struct tpi_info ti;
816 816
817 if (tpi(&ti)) { 817 if (tpi(&ti)) {
818 tsch(schid, (struct irb *)__LC_IRB); 818 tsch(ti.irq, (struct irb *)__LC_IRB);
819 return 0; 819 if (ti.irq == schid)
820 return 0;
820 } 821 }
821 udelay(100); 822 udelay(100);
822 } 823 }
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index ee7a05e0c3ba..fbe4202a3f6f 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -13,7 +13,7 @@
13#include <linux/init.h> 13#include <linux/init.h>
14 14
15#include <asm/ccwdev.h> 15#include <asm/ccwdev.h>
16#include <asm/qdio.h> 16#include <asm/cio.h>
17 17
18#include "cio.h" 18#include "cio.h"
19#include "cio_debug.h" 19#include "cio_debug.h"
@@ -21,7 +21,6 @@
21#include "device.h" 21#include "device.h"
22#include "chsc.h" 22#include "chsc.h"
23#include "ioasm.h" 23#include "ioasm.h"
24#include "qdio.h"
25 24
26int 25int
27device_is_online(struct subchannel *sch) 26device_is_online(struct subchannel *sch)
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 02d01a0de16c..ad3fe5aeb663 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/s390/cio/device_ops.c 2 * drivers/s390/cio/device_ops.c
3 * 3 *
4 * $Revision: 1.56 $ 4 * $Revision: 1.57 $
5 * 5 *
6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
@@ -19,14 +19,12 @@
19 19
20#include <asm/ccwdev.h> 20#include <asm/ccwdev.h>
21#include <asm/idals.h> 21#include <asm/idals.h>
22#include <asm/qdio.h>
23 22
24#include "cio.h" 23#include "cio.h"
25#include "cio_debug.h" 24#include "cio_debug.h"
26#include "css.h" 25#include "css.h"
27#include "chsc.h" 26#include "chsc.h"
28#include "device.h" 27#include "device.h"
29#include "qdio.h"
30 28
31int 29int
32ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) 30ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index c874607d9a80..45480a2bc4c0 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -21,7 +21,7 @@ struct tpi_info {
21 * Some S390 specific IO instructions as inline 21 * Some S390 specific IO instructions as inline
22 */ 22 */
23 23
24extern __inline__ int stsch(int irq, volatile struct schib *addr) 24static inline int stsch(int irq, volatile struct schib *addr)
25{ 25{
26 int ccode; 26 int ccode;
27 27
@@ -36,7 +36,7 @@ extern __inline__ int stsch(int irq, volatile struct schib *addr)
36 return ccode; 36 return ccode;
37} 37}
38 38
39extern __inline__ int msch(int irq, volatile struct schib *addr) 39static inline int msch(int irq, volatile struct schib *addr)
40{ 40{
41 int ccode; 41 int ccode;
42 42
@@ -51,7 +51,7 @@ extern __inline__ int msch(int irq, volatile struct schib *addr)
51 return ccode; 51 return ccode;
52} 52}
53 53
54extern __inline__ int msch_err(int irq, volatile struct schib *addr) 54static inline int msch_err(int irq, volatile struct schib *addr)
55{ 55{
56 int ccode; 56 int ccode;
57 57
@@ -79,7 +79,7 @@ extern __inline__ int msch_err(int irq, volatile struct schib *addr)
79 return ccode; 79 return ccode;
80} 80}
81 81
82extern __inline__ int tsch(int irq, volatile struct irb *addr) 82static inline int tsch(int irq, volatile struct irb *addr)
83{ 83{
84 int ccode; 84 int ccode;
85 85
@@ -94,7 +94,7 @@ extern __inline__ int tsch(int irq, volatile struct irb *addr)
94 return ccode; 94 return ccode;
95} 95}
96 96
97extern __inline__ int tpi( volatile struct tpi_info *addr) 97static inline int tpi( volatile struct tpi_info *addr)
98{ 98{
99 int ccode; 99 int ccode;
100 100
@@ -108,7 +108,7 @@ extern __inline__ int tpi( volatile struct tpi_info *addr)
108 return ccode; 108 return ccode;
109} 109}
110 110
111extern __inline__ int ssch(int irq, volatile struct orb *addr) 111static inline int ssch(int irq, volatile struct orb *addr)
112{ 112{
113 int ccode; 113 int ccode;
114 114
@@ -123,7 +123,7 @@ extern __inline__ int ssch(int irq, volatile struct orb *addr)
123 return ccode; 123 return ccode;
124} 124}
125 125
126extern __inline__ int rsch(int irq) 126static inline int rsch(int irq)
127{ 127{
128 int ccode; 128 int ccode;
129 129
@@ -138,7 +138,7 @@ extern __inline__ int rsch(int irq)
138 return ccode; 138 return ccode;
139} 139}
140 140
141extern __inline__ int csch(int irq) 141static inline int csch(int irq)
142{ 142{
143 int ccode; 143 int ccode;
144 144
@@ -153,7 +153,7 @@ extern __inline__ int csch(int irq)
153 return ccode; 153 return ccode;
154} 154}
155 155
156extern __inline__ int hsch(int irq) 156static inline int hsch(int irq)
157{ 157{
158 int ccode; 158 int ccode;
159 159
@@ -168,7 +168,7 @@ extern __inline__ int hsch(int irq)
168 return ccode; 168 return ccode;
169} 169}
170 170
171extern __inline__ int xsch(int irq) 171static inline int xsch(int irq)
172{ 172{
173 int ccode; 173 int ccode;
174 174
@@ -183,7 +183,7 @@ extern __inline__ int xsch(int irq)
183 return ccode; 183 return ccode;
184} 184}
185 185
186extern __inline__ int chsc(void *chsc_area) 186static inline int chsc(void *chsc_area)
187{ 187{
188 int cc; 188 int cc;
189 189
@@ -198,7 +198,7 @@ extern __inline__ int chsc(void *chsc_area)
198 return cc; 198 return cc;
199} 199}
200 200
201extern __inline__ int iac( void) 201static inline int iac( void)
202{ 202{
203 int ccode; 203 int ccode;
204 204
@@ -210,7 +210,7 @@ extern __inline__ int iac( void)
210 return ccode; 210 return ccode;
211} 211}
212 212
213extern __inline__ int rchp(int chpid) 213static inline int rchp(int chpid)
214{ 214{
215 int ccode; 215 int ccode;
216 216
diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h
index bcabac7a7c46..e319e78b5ea2 100644
--- a/drivers/s390/crypto/z90common.h
+++ b/drivers/s390/crypto/z90common.h
@@ -27,7 +27,7 @@
27#ifndef _Z90COMMON_H_ 27#ifndef _Z90COMMON_H_
28#define _Z90COMMON_H_ 28#define _Z90COMMON_H_
29 29
30#define VERSION_Z90COMMON_H "$Revision: 1.16 $" 30#define VERSION_Z90COMMON_H "$Revision: 1.17 $"
31 31
32 32
33#define RESPBUFFSIZE 256 33#define RESPBUFFSIZE 256
@@ -164,5 +164,4 @@ struct CPRBX {
164#define UMIN(a,b) ((a) < (b) ? (a) : (b)) 164#define UMIN(a,b) ((a) < (b) ? (a) : (b))
165#define IS_EVEN(x) ((x) == (2 * ((x) / 2))) 165#define IS_EVEN(x) ((x) == (2 * ((x) / 2)))
166 166
167
168#endif 167#endif
diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c
index beb6a5e0da22..c215e0889736 100644
--- a/drivers/s390/crypto/z90hardware.c
+++ b/drivers/s390/crypto/z90hardware.c
@@ -32,7 +32,7 @@
32#include "z90crypt.h" 32#include "z90crypt.h"
33#include "z90common.h" 33#include "z90common.h"
34 34
35#define VERSION_Z90HARDWARE_C "$Revision: 1.33 $" 35#define VERSION_Z90HARDWARE_C "$Revision: 1.34 $"
36 36
37char z90hardware_version[] __initdata = 37char z90hardware_version[] __initdata =
38 "z90hardware.o (" VERSION_Z90HARDWARE_C "/" 38 "z90hardware.o (" VERSION_Z90HARDWARE_C "/"
@@ -283,48 +283,6 @@ struct type6_msg {
283 struct CPRB CPRB; 283 struct CPRB CPRB;
284}; 284};
285 285
286union request_msg {
287 union type4_msg t4msg;
288 struct type6_msg t6msg;
289};
290
291struct request_msg_ext {
292 int q_nr;
293 unsigned char *psmid;
294 union request_msg reqMsg;
295};
296
297struct type82_hdr {
298 unsigned char reserved1;
299 unsigned char type;
300 unsigned char reserved2[2];
301 unsigned char reply_code;
302 unsigned char reserved3[3];
303};
304
305#define TYPE82_RSP_CODE 0x82
306
307#define REPLY_ERROR_MACHINE_FAILURE 0x10
308#define REPLY_ERROR_PREEMPT_FAILURE 0x12
309#define REPLY_ERROR_CHECKPT_FAILURE 0x14
310#define REPLY_ERROR_MESSAGE_TYPE 0x20
311#define REPLY_ERROR_INVALID_COMM_CD 0x21
312#define REPLY_ERROR_INVALID_MSG_LEN 0x23
313#define REPLY_ERROR_RESERVD_FIELD 0x24
314#define REPLY_ERROR_FORMAT_FIELD 0x29
315#define REPLY_ERROR_INVALID_COMMAND 0x30
316#define REPLY_ERROR_MALFORMED_MSG 0x40
317#define REPLY_ERROR_RESERVED_FIELDO 0x50
318#define REPLY_ERROR_WORD_ALIGNMENT 0x60
319#define REPLY_ERROR_MESSAGE_LENGTH 0x80
320#define REPLY_ERROR_OPERAND_INVALID 0x82
321#define REPLY_ERROR_OPERAND_SIZE 0x84
322#define REPLY_ERROR_EVEN_MOD_IN_OPND 0x85
323#define REPLY_ERROR_RESERVED_FIELD 0x88
324#define REPLY_ERROR_TRANSPORT_FAIL 0x90
325#define REPLY_ERROR_PACKET_TRUNCATED 0xA0
326#define REPLY_ERROR_ZERO_BUFFER_LEN 0xB0
327
328struct type86_hdr { 286struct type86_hdr {
329 unsigned char reserved1; 287 unsigned char reserved1;
330 unsigned char type; 288 unsigned char type;
@@ -338,7 +296,7 @@ struct type86_hdr {
338#define TYPE86_FMT2 0x02 296#define TYPE86_FMT2 0x02
339 297
340struct type86_fmt2_msg { 298struct type86_fmt2_msg {
341 struct type86_hdr hdr; 299 struct type86_hdr header;
342 unsigned char reserved[4]; 300 unsigned char reserved[4];
343 unsigned char apfs[4]; 301 unsigned char apfs[4];
344 unsigned int count1; 302 unsigned int count1;
@@ -538,6 +496,8 @@ static struct function_and_rules_block static_pke_function_and_rulesX = {
538 {'M','R','P',' ',' ',' ',' ',' '} 496 {'M','R','P',' ',' ',' ',' ',' '}
539}; 497};
540 498
499static unsigned char static_PKE_function_code[2] = {0x50, 0x4B};
500
541struct T6_keyBlock_hdrX { 501struct T6_keyBlock_hdrX {
542 unsigned short blen; 502 unsigned short blen;
543 unsigned short ulen; 503 unsigned short ulen;
@@ -688,9 +648,38 @@ static struct cca_public_sec static_cca_pub_sec = {
688#define RESPONSE_CPRB_SIZE 0x000006B8 648#define RESPONSE_CPRB_SIZE 0x000006B8
689#define RESPONSE_CPRBX_SIZE 0x00000724 649#define RESPONSE_CPRBX_SIZE 0x00000724
690 650
691#define CALLER_HEADER 12 651struct error_hdr {
652 unsigned char reserved1;
653 unsigned char type;
654 unsigned char reserved2[2];
655 unsigned char reply_code;
656 unsigned char reserved3[3];
657};
692 658
693static unsigned char static_PKE_function_code[2] = {0x50, 0x4B}; 659#define TYPE82_RSP_CODE 0x82
660
661#define REP82_ERROR_MACHINE_FAILURE 0x10
662#define REP82_ERROR_PREEMPT_FAILURE 0x12
663#define REP82_ERROR_CHECKPT_FAILURE 0x14
664#define REP82_ERROR_MESSAGE_TYPE 0x20
665#define REP82_ERROR_INVALID_COMM_CD 0x21
666#define REP82_ERROR_INVALID_MSG_LEN 0x23
667#define REP82_ERROR_RESERVD_FIELD 0x24
668#define REP82_ERROR_FORMAT_FIELD 0x29
669#define REP82_ERROR_INVALID_COMMAND 0x30
670#define REP82_ERROR_MALFORMED_MSG 0x40
671#define REP82_ERROR_RESERVED_FIELDO 0x50
672#define REP82_ERROR_WORD_ALIGNMENT 0x60
673#define REP82_ERROR_MESSAGE_LENGTH 0x80
674#define REP82_ERROR_OPERAND_INVALID 0x82
675#define REP82_ERROR_OPERAND_SIZE 0x84
676#define REP82_ERROR_EVEN_MOD_IN_OPND 0x85
677#define REP82_ERROR_RESERVED_FIELD 0x88
678#define REP82_ERROR_TRANSPORT_FAIL 0x90
679#define REP82_ERROR_PACKET_TRUNCATED 0xA0
680#define REP82_ERROR_ZERO_BUFFER_LEN 0xB0
681
682#define CALLER_HEADER 12
694 683
695static inline int 684static inline int
696testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat) 685testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat)
@@ -1212,9 +1201,9 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext)
1212 struct ap_status_word stat_word; 1201 struct ap_status_word stat_word;
1213 enum devstat stat; 1202 enum devstat stat;
1214 int ccode; 1203 int ccode;
1204 u32 *q_nr_p = (u32 *)msg_ext;
1215 1205
1216 ((struct request_msg_ext *) msg_ext)->q_nr = 1206 *q_nr_p = (dev_nr << SKIP_BITL) + cdx;
1217 (dev_nr << SKIP_BITL) + cdx;
1218 PDEBUG("msg_len passed to sen: %d\n", msg_len); 1207 PDEBUG("msg_len passed to sen: %d\n", msg_len);
1219 PDEBUG("q number passed to sen: %02x%02x%02x%02x\n", 1208 PDEBUG("q number passed to sen: %02x%02x%02x%02x\n",
1220 msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3]); 1209 msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3]);
@@ -2104,7 +2093,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
2104 int *respbufflen_p, unsigned char *resp_buff) 2093 int *respbufflen_p, unsigned char *resp_buff)
2105{ 2094{
2106 struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer; 2095 struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer;
2107 struct type82_hdr *t82h_p = (struct type82_hdr *) response; 2096 struct error_hdr *errh_p = (struct error_hdr *) response;
2108 struct type84_hdr *t84h_p = (struct type84_hdr *) response; 2097 struct type84_hdr *t84h_p = (struct type84_hdr *) response;
2109 struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response; 2098 struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response;
2110 int reply_code, service_rc, service_rs, src_l; 2099 int reply_code, service_rc, service_rs, src_l;
@@ -2117,12 +2106,13 @@ convert_response(unsigned char *response, unsigned char *buffer,
2117 service_rc = 0; 2106 service_rc = 0;
2118 service_rs = 0; 2107 service_rs = 0;
2119 src_l = 0; 2108 src_l = 0;
2120 switch (t82h_p->type) { 2109 switch (errh_p->type) {
2121 case TYPE82_RSP_CODE: 2110 case TYPE82_RSP_CODE:
2122 reply_code = t82h_p->reply_code; 2111 reply_code = errh_p->reply_code;
2123 src_p = (unsigned char *)t82h_p; 2112 src_p = (unsigned char *)errh_p;
2124 PRINTK("Hardware error: Type 82 Message Header: " 2113 PRINTK("Hardware error: Type %02X Message Header: "
2125 "%02x%02x%02x%02x%02x%02x%02x%02x\n", 2114 "%02x%02x%02x%02x%02x%02x%02x%02x\n",
2115 errh_p->type,
2126 src_p[0], src_p[1], src_p[2], src_p[3], 2116 src_p[0], src_p[1], src_p[2], src_p[3],
2127 src_p[4], src_p[5], src_p[6], src_p[7]); 2117 src_p[4], src_p[5], src_p[6], src_p[7]);
2128 break; 2118 break;
@@ -2131,7 +2121,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
2131 src_p = response + (int)t84h_p->len - src_l; 2121 src_p = response + (int)t84h_p->len - src_l;
2132 break; 2122 break;
2133 case TYPE86_RSP_CODE: 2123 case TYPE86_RSP_CODE:
2134 reply_code = t86m_p->hdr.reply_code; 2124 reply_code = t86m_p->header.reply_code;
2135 if (reply_code != 0) 2125 if (reply_code != 0)
2136 break; 2126 break;
2137 cprb_p = (struct CPRB *) 2127 cprb_p = (struct CPRB *)
@@ -2143,6 +2133,9 @@ convert_response(unsigned char *response, unsigned char *buffer,
2143 le2toI(cprb_p->ccp_rscode, &service_rs); 2133 le2toI(cprb_p->ccp_rscode, &service_rs);
2144 if ((service_rc == 8) && (service_rs == 66)) 2134 if ((service_rc == 8) && (service_rs == 66))
2145 PDEBUG("Bad block format on PCICC\n"); 2135 PDEBUG("Bad block format on PCICC\n");
2136 else if ((service_rc == 8) && (service_rs == 65))
2137 PDEBUG("Probably an even modulus on "
2138 "PCICC\n");
2146 else if ((service_rc == 8) && (service_rs == 770)) { 2139 else if ((service_rc == 8) && (service_rs == 770)) {
2147 PDEBUG("Invalid key length on PCICC\n"); 2140 PDEBUG("Invalid key length on PCICC\n");
2148 unset_ext_bitlens(); 2141 unset_ext_bitlens();
@@ -2155,7 +2148,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
2155 return REC_USE_PCICA; 2148 return REC_USE_PCICA;
2156 } 2149 }
2157 else 2150 else
2158 PRINTK("service rc/rs: %d/%d\n", 2151 PRINTK("service rc/rs (PCICC): %d/%d\n",
2159 service_rc, service_rs); 2152 service_rc, service_rs);
2160 return REC_OPERAND_INV; 2153 return REC_OPERAND_INV;
2161 } 2154 }
@@ -2169,7 +2162,10 @@ convert_response(unsigned char *response, unsigned char *buffer,
2169 if (service_rc != 0) { 2162 if (service_rc != 0) {
2170 service_rs = (int) cprbx_p->ccp_rscode; 2163 service_rs = (int) cprbx_p->ccp_rscode;
2171 if ((service_rc == 8) && (service_rs == 66)) 2164 if ((service_rc == 8) && (service_rs == 66))
2172 PDEBUG("Bad block format on PCXICC\n"); 2165 PDEBUG("Bad block format on PCIXCC\n");
2166 else if ((service_rc == 8) && (service_rs == 65))
2167 PDEBUG("Probably an even modulus on "
2168 "PCIXCC\n");
2173 else if ((service_rc == 8) && (service_rs == 770)) { 2169 else if ((service_rc == 8) && (service_rs == 770)) {
2174 PDEBUG("Invalid key length on PCIXCC\n"); 2170 PDEBUG("Invalid key length on PCIXCC\n");
2175 unset_ext_bitlens(); 2171 unset_ext_bitlens();
@@ -2182,7 +2178,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
2182 return REC_USE_PCICA; 2178 return REC_USE_PCICA;
2183 } 2179 }
2184 else 2180 else
2185 PRINTK("service rc/rs: %d/%d\n", 2181 PRINTK("service rc/rs (PCIXCC): %d/%d\n",
2186 service_rc, service_rs); 2182 service_rc, service_rs);
2187 return REC_OPERAND_INV; 2183 return REC_OPERAND_INV;
2188 } 2184 }
@@ -2195,20 +2191,25 @@ convert_response(unsigned char *response, unsigned char *buffer,
2195 } 2191 }
2196 break; 2192 break;
2197 default: 2193 default:
2194 src_p = (unsigned char *)errh_p;
2195 PRINTK("Unrecognized Message Header: "
2196 "%02x%02x%02x%02x%02x%02x%02x%02x\n",
2197 src_p[0], src_p[1], src_p[2], src_p[3],
2198 src_p[4], src_p[5], src_p[6], src_p[7]);
2198 return REC_BAD_MESSAGE; 2199 return REC_BAD_MESSAGE;
2199 } 2200 }
2200 2201
2201 if (reply_code) 2202 if (reply_code)
2202 switch (reply_code) { 2203 switch (reply_code) {
2203 case REPLY_ERROR_OPERAND_INVALID: 2204 case REP82_ERROR_OPERAND_INVALID:
2204 return REC_OPERAND_INV; 2205 return REC_OPERAND_INV;
2205 case REPLY_ERROR_OPERAND_SIZE: 2206 case REP82_ERROR_OPERAND_SIZE:
2206 return REC_OPERAND_SIZE; 2207 return REC_OPERAND_SIZE;
2207 case REPLY_ERROR_EVEN_MOD_IN_OPND: 2208 case REP82_ERROR_EVEN_MOD_IN_OPND:
2208 return REC_EVEN_MOD; 2209 return REC_EVEN_MOD;
2209 case REPLY_ERROR_MESSAGE_TYPE: 2210 case REP82_ERROR_MESSAGE_TYPE:
2210 return WRONG_DEVICE_TYPE; 2211 return WRONG_DEVICE_TYPE;
2211 case REPLY_ERROR_TRANSPORT_FAIL: 2212 case REP82_ERROR_TRANSPORT_FAIL:
2212 PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n", 2213 PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n",
2213 t86m_p->apfs[0], t86m_p->apfs[1], 2214 t86m_p->apfs[0], t86m_p->apfs[1],
2214 t86m_p->apfs[2], t86m_p->apfs[3]); 2215 t86m_p->apfs[2], t86m_p->apfs[3]);
@@ -2229,7 +2230,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
2229 PDEBUG("Length returned = %d\n", src_l); 2230 PDEBUG("Length returned = %d\n", src_l);
2230 tgt_p = resp_buff + icaMsg_p->outputdatalength - src_l; 2231 tgt_p = resp_buff + icaMsg_p->outputdatalength - src_l;
2231 memcpy(tgt_p, src_p, src_l); 2232 memcpy(tgt_p, src_p, src_l);
2232 if ((t82h_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) { 2233 if ((errh_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) {
2233 memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l); 2234 memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l);
2234 if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l)) 2235 if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l))
2235 return REC_INVALID_PAD; 2236 return REC_INVALID_PAD;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 9ec29bb41b28..6aeef3bacc33 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -31,6 +31,7 @@
31#include <linux/init.h> 31#include <linux/init.h>
32#include <linux/interrupt.h> // for tasklets 32#include <linux/interrupt.h> // for tasklets
33#include <linux/ioctl32.h> 33#include <linux/ioctl32.h>
34#include <linux/miscdevice.h>
34#include <linux/module.h> 35#include <linux/module.h>
35#include <linux/moduleparam.h> 36#include <linux/moduleparam.h>
36#include <linux/kobject_uevent.h> 37#include <linux/kobject_uevent.h>
@@ -39,19 +40,8 @@
39#include <linux/version.h> 40#include <linux/version.h>
40#include "z90crypt.h" 41#include "z90crypt.h"
41#include "z90common.h" 42#include "z90common.h"
42#ifndef Z90CRYPT_USE_HOTPLUG
43#include <linux/miscdevice.h>
44#endif
45
46#define VERSION_CODE(vers, rel, seq) (((vers)<<16) | ((rel)<<8) | (seq))
47#if LINUX_VERSION_CODE < VERSION_CODE(2,4,0) /* version < 2.4 */
48# error "This kernel is too old: not supported"
49#endif
50#if LINUX_VERSION_CODE > VERSION_CODE(2,7,0) /* version > 2.6 */
51# error "This kernel is too recent: not supported by this file"
52#endif
53 43
54#define VERSION_Z90MAIN_C "$Revision: 1.57 $" 44#define VERSION_Z90MAIN_C "$Revision: 1.62 $"
55 45
56static char z90main_version[] __initdata = 46static char z90main_version[] __initdata =
57 "z90main.o (" VERSION_Z90MAIN_C "/" 47 "z90main.o (" VERSION_Z90MAIN_C "/"
@@ -63,21 +53,12 @@ extern char z90hardware_version[];
63 * Defaults that may be modified. 53 * Defaults that may be modified.
64 */ 54 */
65 55
66#ifndef Z90CRYPT_USE_HOTPLUG
67/** 56/**
68 * You can specify a different minor at compile time. 57 * You can specify a different minor at compile time.
69 */ 58 */
70#ifndef Z90CRYPT_MINOR 59#ifndef Z90CRYPT_MINOR
71#define Z90CRYPT_MINOR MISC_DYNAMIC_MINOR 60#define Z90CRYPT_MINOR MISC_DYNAMIC_MINOR
72#endif 61#endif
73#else
74/**
75 * You can specify a different major at compile time.
76 */
77#ifndef Z90CRYPT_MAJOR
78#define Z90CRYPT_MAJOR 0
79#endif
80#endif
81 62
82/** 63/**
83 * You can specify a different domain at compile time or on the insmod 64 * You can specify a different domain at compile time or on the insmod
@@ -97,7 +78,7 @@ extern char z90hardware_version[];
97 * older than CLEANUPTIME seconds in the past. 78 * older than CLEANUPTIME seconds in the past.
98 */ 79 */
99#ifndef CLEANUPTIME 80#ifndef CLEANUPTIME
100#define CLEANUPTIME 20 81#define CLEANUPTIME 15
101#endif 82#endif
102 83
103/** 84/**
@@ -298,6 +279,10 @@ struct z90crypt {
298 * it contains the request; at READ, the response. The function 279 * it contains the request; at READ, the response. The function
299 * send_to_crypto_device converts the request to device-dependent 280 * send_to_crypto_device converts the request to device-dependent
300 * form and use the caller's OPEN-allocated buffer for the response. 281 * form and use the caller's OPEN-allocated buffer for the response.
282 *
283 * For the contents of caller_dev_dep_req and caller_dev_dep_req_p
284 * because that points to it, see the discussion in z90hardware.c.
285 * Search for "extended request message block".
301 */ 286 */
302struct caller { 287struct caller {
303 int caller_buf_l; // length of original request 288 int caller_buf_l; // length of original request
@@ -398,24 +383,9 @@ static int z90crypt_status_write(struct file *, const char __user *,
398 unsigned long, void *); 383 unsigned long, void *);
399 384
400/** 385/**
401 * Hotplug support
402 */
403
404#ifdef Z90CRYPT_USE_HOTPLUG
405#define Z90CRYPT_HOTPLUG_ADD 1
406#define Z90CRYPT_HOTPLUG_REMOVE 2
407
408static void z90crypt_hotplug_event(int, int, int);
409#endif
410
411/**
412 * Storage allocated at initialization and used throughout the life of 386 * Storage allocated at initialization and used throughout the life of
413 * this insmod 387 * this insmod
414 */ 388 */
415#ifdef Z90CRYPT_USE_HOTPLUG
416static int z90crypt_major = Z90CRYPT_MAJOR;
417#endif
418
419static int domain = DOMAIN_INDEX; 389static int domain = DOMAIN_INDEX;
420static struct z90crypt z90crypt; 390static struct z90crypt z90crypt;
421static int quiesce_z90crypt; 391static int quiesce_z90crypt;
@@ -444,14 +414,12 @@ static struct file_operations z90crypt_fops = {
444 .release = z90crypt_release 414 .release = z90crypt_release
445}; 415};
446 416
447#ifndef Z90CRYPT_USE_HOTPLUG
448static struct miscdevice z90crypt_misc_device = { 417static struct miscdevice z90crypt_misc_device = {
449 .minor = Z90CRYPT_MINOR, 418 .minor = Z90CRYPT_MINOR,
450 .name = DEV_NAME, 419 .name = DEV_NAME,
451 .fops = &z90crypt_fops, 420 .fops = &z90crypt_fops,
452 .devfs_name = DEV_NAME 421 .devfs_name = DEV_NAME
453}; 422};
454#endif
455 423
456/** 424/**
457 * Documentation values. 425 * Documentation values.
@@ -603,7 +571,6 @@ z90crypt_init_module(void)
603 return -EINVAL; 571 return -EINVAL;
604 } 572 }
605 573
606#ifndef Z90CRYPT_USE_HOTPLUG
607 /* Register as misc device with given minor (or get a dynamic one). */ 574 /* Register as misc device with given minor (or get a dynamic one). */
608 result = misc_register(&z90crypt_misc_device); 575 result = misc_register(&z90crypt_misc_device);
609 if (result < 0) { 576 if (result < 0) {
@@ -611,18 +578,6 @@ z90crypt_init_module(void)
611 z90crypt_misc_device.minor, result); 578 z90crypt_misc_device.minor, result);
612 return result; 579 return result;
613 } 580 }
614#else
615 /* Register the major (or get a dynamic one). */
616 result = register_chrdev(z90crypt_major, REG_NAME, &z90crypt_fops);
617 if (result < 0) {
618 PRINTKW("register_chrdev (major %d) failed with %d.\n",
619 z90crypt_major, result);
620 return result;
621 }
622
623 if (z90crypt_major == 0)
624 z90crypt_major = result;
625#endif
626 581
627 PDEBUG("Registered " DEV_NAME " with result %d\n", result); 582 PDEBUG("Registered " DEV_NAME " with result %d\n", result);
628 583
@@ -645,11 +600,6 @@ z90crypt_init_module(void)
645 } else 600 } else
646 PRINTK("No devices at startup\n"); 601 PRINTK("No devices at startup\n");
647 602
648#ifdef Z90CRYPT_USE_HOTPLUG
649 /* generate hotplug event for device node generation */
650 z90crypt_hotplug_event(z90crypt_major, 0, Z90CRYPT_HOTPLUG_ADD);
651#endif
652
653 /* Initialize globals. */ 603 /* Initialize globals. */
654 spin_lock_init(&queuespinlock); 604 spin_lock_init(&queuespinlock);
655 605
@@ -701,17 +651,10 @@ z90crypt_init_module(void)
701 return 0; // success 651 return 0; // success
702 652
703init_module_cleanup: 653init_module_cleanup:
704#ifndef Z90CRYPT_USE_HOTPLUG
705 if ((nresult = misc_deregister(&z90crypt_misc_device))) 654 if ((nresult = misc_deregister(&z90crypt_misc_device)))
706 PRINTK("misc_deregister failed with %d.\n", nresult); 655 PRINTK("misc_deregister failed with %d.\n", nresult);
707 else 656 else
708 PDEBUG("misc_deregister successful.\n"); 657 PDEBUG("misc_deregister successful.\n");
709#else
710 if ((nresult = unregister_chrdev(z90crypt_major, REG_NAME)))
711 PRINTK("unregister_chrdev failed with %d.\n", nresult);
712 else
713 PDEBUG("unregister_chrdev successful.\n");
714#endif
715 658
716 return result; // failure 659 return result; // failure
717} 660}
@@ -728,19 +671,10 @@ z90crypt_cleanup_module(void)
728 671
729 remove_proc_entry("driver/z90crypt", 0); 672 remove_proc_entry("driver/z90crypt", 0);
730 673
731#ifndef Z90CRYPT_USE_HOTPLUG
732 if ((nresult = misc_deregister(&z90crypt_misc_device))) 674 if ((nresult = misc_deregister(&z90crypt_misc_device)))
733 PRINTK("misc_deregister failed with %d.\n", nresult); 675 PRINTK("misc_deregister failed with %d.\n", nresult);
734 else 676 else
735 PDEBUG("misc_deregister successful.\n"); 677 PDEBUG("misc_deregister successful.\n");
736#else
737 z90crypt_hotplug_event(z90crypt_major, 0, Z90CRYPT_HOTPLUG_REMOVE);
738
739 if ((nresult = unregister_chrdev(z90crypt_major, REG_NAME)))
740 PRINTK("unregister_chrdev failed with %d.\n", nresult);
741 else
742 PDEBUG("unregister_chrdev successful.\n");
743#endif
744 678
745 /* Remove the tasks */ 679 /* Remove the tasks */
746 tasklet_kill(&reader_tasklet); 680 tasklet_kill(&reader_tasklet);
@@ -748,6 +682,9 @@ z90crypt_cleanup_module(void)
748 del_timer(&config_timer); 682 del_timer(&config_timer);
749 del_timer(&cleanup_timer); 683 del_timer(&cleanup_timer);
750 684
685 if (z90_device_work)
686 destroy_workqueue(z90_device_work);
687
751 destroy_z90crypt(); 688 destroy_z90crypt();
752 689
753 PRINTKN("Unloaded.\n"); 690 PRINTKN("Unloaded.\n");
@@ -766,8 +703,6 @@ z90crypt_cleanup_module(void)
766 * z90crypt_status_write 703 * z90crypt_status_write
767 * disable_card 704 * disable_card
768 * enable_card 705 * enable_card
769 * scan_char
770 * scan_string
771 * 706 *
772 * Helper functions: 707 * Helper functions:
773 * z90crypt_rsa 708 * z90crypt_rsa
@@ -1057,9 +992,10 @@ remove_device(struct device *device_p)
1057 * The MCL must be applied and the newer bitlengths enabled for these to work. 992 * The MCL must be applied and the newer bitlengths enabled for these to work.
1058 * 993 *
1059 * Card Type Old limit New limit 994 * Card Type Old limit New limit
995 * PCICA ??-2048 same (the lower limit is less than 128 bit...)
1060 * PCICC 512-1024 512-2048 996 * PCICC 512-1024 512-2048
1061 * PCIXCC_MCL2 512-2048 no change (applying this MCL == card is MCL3+) 997 * PCIXCC_MCL2 512-2048 ----- (applying any GA LIC will make an MCL3 card)
1062 * PCIXCC_MCL3 512-2048 128-2048 998 * PCIXCC_MCL3 ----- 128-2048
1063 * CEX2C 512-2048 128-2048 999 * CEX2C 512-2048 128-2048
1064 * 1000 *
1065 * ext_bitlens (extended bitlengths) is a global, since you should not apply an 1001 * ext_bitlens (extended bitlengths) is a global, since you should not apply an
@@ -1104,7 +1040,7 @@ select_device_type(int *dev_type_p, int bytelength)
1104 if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) { 1040 if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) {
1105 /** 1041 /**
1106 * bitlength is a factor, PCICA is the most capable, even with 1042 * bitlength is a factor, PCICA is the most capable, even with
1107 * the new MCL. 1043 * the new MCL for PCIXCC.
1108 */ 1044 */
1109 if ((bytelength < PCIXCC_MIN_MOD_SIZE) || 1045 if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||
1110 (!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) { 1046 (!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {
@@ -2144,73 +2080,15 @@ enable_card(int card_index)
2144 z90crypt.hdware_info->type_mask[devp->dev_type].user_disabled_count--; 2080 z90crypt.hdware_info->type_mask[devp->dev_type].user_disabled_count--;
2145} 2081}
2146 2082
2147static inline int
2148scan_char(unsigned char *bf, unsigned int len,
2149 unsigned int *offs, unsigned int *p_eof, unsigned char c)
2150{
2151 unsigned int i, found;
2152
2153 found = 0;
2154 for (i = 0; i < len; i++) {
2155 if (bf[i] == c) {
2156 found = 1;
2157 break;
2158 }
2159 if (bf[i] == '\0') {
2160 *p_eof = 1;
2161 break;
2162 }
2163 if (bf[i] == '\n') {
2164 break;
2165 }
2166 }
2167 *offs = i+1;
2168 return found;
2169}
2170
2171static inline int
2172scan_string(unsigned char *bf, unsigned int len,
2173 unsigned int *offs, unsigned int *p_eof, unsigned char *s)
2174{
2175 unsigned int temp_len, temp_offs, found, eof;
2176
2177 temp_len = temp_offs = found = eof = 0;
2178 while (!eof && !found) {
2179 found = scan_char(bf+temp_len, len-temp_len,
2180 &temp_offs, &eof, *s);
2181
2182 temp_len += temp_offs;
2183 if (eof) {
2184 found = 0;
2185 break;
2186 }
2187
2188 if (found) {
2189 if (len >= temp_offs+strlen(s)) {
2190 found = !strncmp(bf+temp_len-1, s, strlen(s));
2191 if (found) {
2192 *offs = temp_len+strlen(s)-1;
2193 break;
2194 }
2195 } else {
2196 found = 0;
2197 *p_eof = 1;
2198 break;
2199 }
2200 }
2201 }
2202 return found;
2203}
2204
2205static int 2083static int
2206z90crypt_status_write(struct file *file, const char __user *buffer, 2084z90crypt_status_write(struct file *file, const char __user *buffer,
2207 unsigned long count, void *data) 2085 unsigned long count, void *data)
2208{ 2086{
2209 int i, j, len, offs, found, eof; 2087 int j, eol;
2210 unsigned char *lbuf; 2088 unsigned char *lbuf, *ptr;
2211 unsigned int local_count; 2089 unsigned int local_count;
2212 2090
2213#define LBUFSIZE 600 2091#define LBUFSIZE 1200
2214 lbuf = kmalloc(LBUFSIZE, GFP_KERNEL); 2092 lbuf = kmalloc(LBUFSIZE, GFP_KERNEL);
2215 if (!lbuf) { 2093 if (!lbuf) {
2216 PRINTK("kmalloc failed!\n"); 2094 PRINTK("kmalloc failed!\n");
@@ -2227,49 +2105,46 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
2227 return -EFAULT; 2105 return -EFAULT;
2228 } 2106 }
2229 2107
2230 lbuf[local_count-1] = '\0'; 2108 lbuf[local_count] = '\0';
2231 2109
2232 len = 0; 2110 ptr = strstr(lbuf, "Online devices");
2233 eof = 0; 2111 if (ptr == 0) {
2234 found = 0; 2112 PRINTK("Unable to parse data (missing \"Online devices\")\n");
2235 while (!eof) { 2113 kfree(lbuf);
2236 found = scan_string(lbuf+len, local_count-len, &offs, &eof, 2114 return count;
2237 "Online devices");
2238 len += offs;
2239 if (found == 1)
2240 break;
2241 } 2115 }
2242 2116
2243 if (eof) { 2117 ptr = strstr(ptr, "\n");
2118 if (ptr == 0) {
2119 PRINTK("Unable to parse data (missing newline after \"Online devices\")\n");
2244 kfree(lbuf); 2120 kfree(lbuf);
2245 return count; 2121 return count;
2246 } 2122 }
2123 ptr++;
2247 2124
2248 if (found) 2125 if (strstr(ptr, "Waiting work element counts") == NULL) {
2249 found = scan_char(lbuf+len, local_count-len, &offs, &eof, '\n'); 2126 PRINTK("Unable to parse data (missing \"Waiting work element counts\")\n");
2250
2251 if (!found || eof) {
2252 kfree(lbuf); 2127 kfree(lbuf);
2253 return count; 2128 return count;
2254 } 2129 }
2255 2130
2256 len += offs;
2257 j = 0; 2131 j = 0;
2258 for (i = 0; i < 80; i++) { 2132 eol = 0;
2259 switch (*(lbuf+len+i)) { 2133 while ((j < 64) && (*ptr != '\0')) {
2134 switch (*ptr) {
2260 case '\t': 2135 case '\t':
2261 case ' ': 2136 case ' ':
2262 break; 2137 break;
2263 case '\n': 2138 case '\n':
2264 default: 2139 default:
2265 eof = 1; 2140 eol = 1;
2266 break; 2141 break;
2267 case '0': 2142 case '0': // no device
2268 case '1': 2143 case '1': // PCICA
2269 case '2': 2144 case '2': // PCICC
2270 case '3': 2145 case '3': // PCIXCC_MCL2
2271 case '4': 2146 case '4': // PCIXCC_MCL3
2272 case '5': 2147 case '5': // CEX2C
2273 j++; 2148 j++;
2274 break; 2149 break;
2275 case 'd': 2150 case 'd':
@@ -2283,8 +2158,9 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
2283 j++; 2158 j++;
2284 break; 2159 break;
2285 } 2160 }
2286 if (eof) 2161 if (eol)
2287 break; 2162 break;
2163 ptr++;
2288 } 2164 }
2289 2165
2290 kfree(lbuf); 2166 kfree(lbuf);
@@ -3479,45 +3355,5 @@ probe_PCIXCC_type(struct device *devPtr)
3479 return rv; 3355 return rv;
3480} 3356}
3481 3357
3482#ifdef Z90CRYPT_USE_HOTPLUG
3483static void
3484z90crypt_hotplug_event(int dev_major, int dev_minor, int action)
3485{
3486#ifdef CONFIG_HOTPLUG
3487 char *argv[3];
3488 char *envp[6];
3489 char major[20];
3490 char minor[20];
3491
3492 sprintf(major, "MAJOR=%d", dev_major);
3493 sprintf(minor, "MINOR=%d", dev_minor);
3494
3495 argv[0] = hotplug_path;
3496 argv[1] = "z90crypt";
3497 argv[2] = 0;
3498
3499 envp[0] = "HOME=/";
3500 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
3501
3502 switch (action) {
3503 case Z90CRYPT_HOTPLUG_ADD:
3504 envp[2] = "ACTION=add";
3505 break;
3506 case Z90CRYPT_HOTPLUG_REMOVE:
3507 envp[2] = "ACTION=remove";
3508 break;
3509 default:
3510 BUG();
3511 break;
3512 }
3513 envp[3] = major;
3514 envp[4] = minor;
3515 envp[5] = 0;
3516
3517 call_usermodehelper(argv[0], argv, envp, 0);
3518#endif
3519}
3520#endif
3521
3522module_init(z90crypt_init_module); 3358module_init(z90crypt_init_module);
3523module_exit(z90crypt_cleanup_module); 3359module_exit(z90crypt_cleanup_module);
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 24c0af49c25c..3092473991a7 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -2,9 +2,9 @@
2 * drivers/s390/net/claw.c 2 * drivers/s390/net/claw.c
3 * ESCON CLAW network driver 3 * ESCON CLAW network driver
4 * 4 *
5 * $Revision: 1.35 $ $Date: 2005/03/24 12:25:38 $ 5 * $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $
6 * 6 *
7 * Linux fo zSeries version 7 * Linux for zSeries version
8 * Copyright (C) 2002,2005 IBM Corporation 8 * Copyright (C) 2002,2005 IBM Corporation
9 * Author(s) Original code written by: 9 * Author(s) Original code written by:
10 * Kazuo Iimura (iimura@jp.ibm.com) 10 * Kazuo Iimura (iimura@jp.ibm.com)
@@ -431,12 +431,12 @@ claw_pack_skb(struct claw_privbk *privptr)
431 if (!skb_queue_empty(&p_ch->collect_queue)) { 431 if (!skb_queue_empty(&p_ch->collect_queue)) {
432 /* some data */ 432 /* some data */
433 held_skb = skb_dequeue(&p_ch->collect_queue); 433 held_skb = skb_dequeue(&p_ch->collect_queue);
434 if (p_env->packing != DO_PACKED)
435 return held_skb;
436 if (held_skb) 434 if (held_skb)
437 atomic_dec(&held_skb->users); 435 dev_kfree_skb_any(held_skb);
438 else 436 else
439 return NULL; 437 return NULL;
438 if (p_env->packing != DO_PACKED)
439 return held_skb;
440 /* get a new SKB we will pack at least one */ 440 /* get a new SKB we will pack at least one */
441 new_skb = dev_alloc_skb(p_env->write_size); 441 new_skb = dev_alloc_skb(p_env->write_size);
442 if (new_skb == NULL) { 442 if (new_skb == NULL) {
@@ -455,7 +455,7 @@ claw_pack_skb(struct claw_privbk *privptr)
455 privptr->stats.tx_packets++; 455 privptr->stats.tx_packets++;
456 so_far += held_skb->len; 456 so_far += held_skb->len;
457 pkt_cnt++; 457 pkt_cnt++;
458 dev_kfree_skb_irq(held_skb); 458 dev_kfree_skb_any(held_skb);
459 held_skb = skb_dequeue(&p_ch->collect_queue); 459 held_skb = skb_dequeue(&p_ch->collect_queue);
460 if (held_skb) 460 if (held_skb)
461 atomic_dec(&held_skb->users); 461 atomic_dec(&held_skb->users);
@@ -1092,7 +1092,7 @@ claw_release(struct net_device *dev)
1092 } 1092 }
1093 } 1093 }
1094 if (privptr->pk_skb != NULL) { 1094 if (privptr->pk_skb != NULL) {
1095 dev_kfree_skb(privptr->pk_skb); 1095 dev_kfree_skb_any(privptr->pk_skb);
1096 privptr->pk_skb = NULL; 1096 privptr->pk_skb = NULL;
1097 } 1097 }
1098 if(privptr->buffs_alloc != 1) { 1098 if(privptr->buffs_alloc != 1) {
@@ -2016,7 +2016,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
2016 p_buf=(struct ccwbk*)privptr->p_end_ccw; 2016 p_buf=(struct ccwbk*)privptr->p_end_ccw;
2017 dumpit((char *)p_buf, sizeof(struct endccw)); 2017 dumpit((char *)p_buf, sizeof(struct endccw));
2018#endif 2018#endif
2019 dev_kfree_skb(skb); 2019 dev_kfree_skb_any(skb);
2020 if (linkid==0) { 2020 if (linkid==0) {
2021 lock=LOCK_NO; 2021 lock=LOCK_NO;
2022 } 2022 }
@@ -4061,7 +4061,7 @@ claw_purge_skb_queue(struct sk_buff_head *q)
4061 4061
4062 while ((skb = skb_dequeue(q))) { 4062 while ((skb = skb_dequeue(q))) {
4063 atomic_dec(&skb->users); 4063 atomic_dec(&skb->users);
4064 dev_kfree_skb_irq(skb); 4064 dev_kfree_skb_any(skb);
4065 } 4065 }
4066} 4066}
4067 4067
@@ -4410,7 +4410,7 @@ claw_init(void)
4410#else 4410#else
4411 "compiled into kernel " 4411 "compiled into kernel "
4412#endif 4412#endif
4413 " $Revision: 1.35 $ $Date: 2005/03/24 12:25:38 $ \n"); 4413 " $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ \n");
4414 4414
4415 4415
4416#ifdef FUNCTRACE 4416#ifdef FUNCTRACE
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 5bb255e02acc..4191fd9d4d11 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -240,7 +240,7 @@ s390_revalidate_registers(struct mci *mci)
240 * Floating point control register can't be restored. 240 * Floating point control register can't be restored.
241 * Task will be terminated. 241 * Task will be terminated.
242 */ 242 */
243 asm volatile ("lfpc 0(%0)" : : "a" (&zero)); 243 asm volatile ("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
244 kill_task = 1; 244 kill_task = 1;
245 245
246 } 246 }