diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/Kconfig | 2 | ||||
-rw-r--r-- | drivers/s390/block/dasd.c | 19 | ||||
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 8 | ||||
-rw-r--r-- | drivers/s390/block/dasd_diag.c | 334 | ||||
-rw-r--r-- | drivers/s390/block/dasd_diag.h | 105 | ||||
-rw-r--r-- | drivers/s390/block/dasd_genhd.c | 10 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 3 | ||||
-rw-r--r-- | drivers/s390/block/dasd_ioctl.c | 17 | ||||
-rw-r--r-- | drivers/s390/block/dasd_proc.c | 8 | ||||
-rw-r--r-- | drivers/s390/char/raw3270.c | 16 | ||||
-rw-r--r-- | drivers/s390/cio/cio.c | 7 | ||||
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 3 | ||||
-rw-r--r-- | drivers/s390/cio/device_ops.c | 4 | ||||
-rw-r--r-- | drivers/s390/cio/ioasm.h | 26 | ||||
-rw-r--r-- | drivers/s390/crypto/z90common.h | 3 | ||||
-rw-r--r-- | drivers/s390/crypto/z90hardware.c | 127 | ||||
-rw-r--r-- | drivers/s390/crypto/z90main.c | 246 | ||||
-rw-r--r-- | drivers/s390/net/claw.c | 20 | ||||
-rw-r--r-- | drivers/s390/s390mach.c | 2 |
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 | ||
50 | config DASD_DIAG | 50 | config 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 | ||
36 | MODULE_LICENSE("GPL"); | 34 | MODULE_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 | |||
38 | struct dasd_discipline dasd_diag_discipline; | 47 | struct dasd_discipline dasd_diag_discipline; |
39 | 48 | ||
40 | struct dasd_diag_private { | 49 | struct 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 | ||
47 | struct dasd_diag_req { | 56 | struct 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 | ||
61 | static 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. */ | ||
52 | static __inline__ int | 67 | static __inline__ int |
53 | dia250(void *iob, int cmd) | 68 | dia250(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. */ | ||
81 | static __inline__ int | 112 | static __inline__ int |
82 | mdsk_init_io(struct dasd_device * device, int blocksize, int offset, int size) | 113 | mdsk_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. */ | ||
103 | static __inline__ int | 139 | static __inline__ int |
104 | mdsk_term_io(struct dasd_device * device) | 140 | mdsk_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. */ | ||
156 | static void | ||
157 | dasd_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. */ | ||
118 | static int | 170 | static int |
119 | dasd_start_diag(struct dasd_ccw_req * cqr) | 171 | dasd_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. */ | ||
224 | static int | ||
225 | dasd_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. */ | ||
153 | static void | 239 | static void |
154 | dasd_ext_handler(struct pt_regs *regs, __u16 code) | 240 | dasd_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. */ | ||
221 | static int | 326 | static int |
222 | dasd_diag_check_device(struct dasd_device *device) | 327 | dasd_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. */ | ||
323 | static int | 444 | static int |
324 | dasd_diag_fill_geometry(struct dasd_device *device, struct hd_geometry *geo) | 445 | dasd_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. */ | ||
352 | static struct dasd_ccw_req * | 475 | static struct dasd_ccw_req * |
353 | dasd_diag_build_cp(struct dasd_device * device, struct request *req) | 476 | dasd_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. */ | ||
423 | static int | 549 | static int |
424 | dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req) | 550 | dasd_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. */ | ||
433 | static int | 560 | static int |
434 | dasd_diag_fill_info(struct dasd_device * device, | 561 | dasd_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 | */ | ||
471 | struct dasd_discipline dasd_diag_discipline = { | 586 | struct 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) | |||
506 | static void __exit | 622 | static void __exit |
507 | dasd_diag_cleanup(void) | 623 | dasd_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 | ||
521 | module_init(dasd_diag_init); | 630 | module_init(dasd_diag_init); |
522 | module_exit(dasd_diag_cleanup); | 631 | module_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 | |||
22 | struct dasd_diag_characteristics { | 34 | struct 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 | ||
47 | struct 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 | |||
72 | typedef u64 blocknum_t; | ||
73 | typedef s64 sblocknum_t; | ||
74 | |||
75 | struct 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 | |||
84 | struct 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 | |||
96 | struct 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 | |||
113 | typedef u32 blocknum_t; | ||
114 | typedef s32 sblocknum_t; | ||
115 | |||
35 | struct dasd_diag_bio { | 116 | struct 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 | ||
44 | struct dasd_diag_init_io { | 125 | struct 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 | ||
54 | struct dasd_diag_rw_io { | 136 | struct 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 | |||
31 | dasd_gendisk_alloc(struct dasd_device *device) | 31 | dasd_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 | ||
26 | int | 25 | int |
27 | device_is_online(struct subchannel *sch) | 26 | device_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 | ||
31 | int | 29 | int |
32 | ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) | 30 | ccw_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 | ||
24 | extern __inline__ int stsch(int irq, volatile struct schib *addr) | 24 | static 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 | ||
39 | extern __inline__ int msch(int irq, volatile struct schib *addr) | 39 | static 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 | ||
54 | extern __inline__ int msch_err(int irq, volatile struct schib *addr) | 54 | static 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 | ||
82 | extern __inline__ int tsch(int irq, volatile struct irb *addr) | 82 | static 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 | ||
97 | extern __inline__ int tpi( volatile struct tpi_info *addr) | 97 | static 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 | ||
111 | extern __inline__ int ssch(int irq, volatile struct orb *addr) | 111 | static 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 | ||
126 | extern __inline__ int rsch(int irq) | 126 | static 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 | ||
141 | extern __inline__ int csch(int irq) | 141 | static 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 | ||
156 | extern __inline__ int hsch(int irq) | 156 | static 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 | ||
171 | extern __inline__ int xsch(int irq) | 171 | static 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 | ||
186 | extern __inline__ int chsc(void *chsc_area) | 186 | static 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 | ||
201 | extern __inline__ int iac( void) | 201 | static 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 | ||
213 | extern __inline__ int rchp(int chpid) | 213 | static 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 | ||
37 | char z90hardware_version[] __initdata = | 37 | char 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 | ||
286 | union request_msg { | ||
287 | union type4_msg t4msg; | ||
288 | struct type6_msg t6msg; | ||
289 | }; | ||
290 | |||
291 | struct request_msg_ext { | ||
292 | int q_nr; | ||
293 | unsigned char *psmid; | ||
294 | union request_msg reqMsg; | ||
295 | }; | ||
296 | |||
297 | struct 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 | |||
328 | struct type86_hdr { | 286 | struct 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 | ||
340 | struct type86_fmt2_msg { | 298 | struct 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 | ||
499 | static unsigned char static_PKE_function_code[2] = {0x50, 0x4B}; | ||
500 | |||
541 | struct T6_keyBlock_hdrX { | 501 | struct 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 | 651 | struct 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 | ||
693 | static 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 | ||
695 | static inline int | 684 | static inline int |
696 | testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat) | 685 | testq(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 | ||
56 | static char z90main_version[] __initdata = | 46 | static 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 | */ |
302 | struct caller { | 287 | struct 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 | |||
408 | static 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 | ||
416 | static int z90crypt_major = Z90CRYPT_MAJOR; | ||
417 | #endif | ||
418 | |||
419 | static int domain = DOMAIN_INDEX; | 389 | static int domain = DOMAIN_INDEX; |
420 | static struct z90crypt z90crypt; | 390 | static struct z90crypt z90crypt; |
421 | static int quiesce_z90crypt; | 391 | static 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 | ||
448 | static struct miscdevice z90crypt_misc_device = { | 417 | static 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 | ||
703 | init_module_cleanup: | 653 | init_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 | ||
2147 | static inline int | ||
2148 | scan_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 | |||
2171 | static inline int | ||
2172 | scan_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 | |||
2205 | static int | 2083 | static int |
2206 | z90crypt_status_write(struct file *file, const char __user *buffer, | 2084 | z90crypt_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 | ||
3483 | static void | ||
3484 | z90crypt_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 | |||
3522 | module_init(z90crypt_init_module); | 3358 | module_init(z90crypt_init_module); |
3523 | module_exit(z90crypt_cleanup_module); | 3359 | module_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 | } |