diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-24 15:06:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-24 15:06:02 -0400 |
commit | 0d66cba1ac3ad38614077443d604d6a09cec99de (patch) | |
tree | 383981fd93c7e6d467fb239edd51f935f1a481dd /drivers | |
parent | 4637f40f200063973553ce3c4c1ac6c247e4535c (diff) | |
parent | 5bd418784a2764a8d9de177a5462bfc008fd334a (diff) |
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (29 commits)
[S390] cpu hotplug: fix external interrupt subclass mask handling
[S390] oprofile: dont access lowcore
[S390] oprofile: add missing irq stats counter
[S390] Ignore sendmmsg system call note wired up warning
[S390] s390,oprofile: fix compile error for !CONFIG_SMP
[S390] s390,oprofile: fix alert counter increment
[S390] Remove unused includes in process.c
[S390] get CPC image name
[S390] sclp: event buffer dissection
[S390] chsc: process channel-path-availability information
[S390] refactor page table functions for better pgste support
[S390] merge page_test_dirty and page_clear_dirty
[S390] qdio: prevent compile warning
[S390] sclp: remove unnecessary sendmask check
[S390] convert old cpumask API into new one
[S390] pfault: cleanup code
[S390] pfault: cpu hotplug vs missing completion interrupts
[S390] smp: add __noreturn attribute to cpu_die()
[S390] percpu: implement arch specific irqsafe_cpu_ops
[S390] vdso: disable gcov profiling
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/crypto/Kconfig | 2 | ||||
-rw-r--r-- | drivers/s390/block/dasd_alias.c | 4 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 11 | ||||
-rw-r--r-- | drivers/s390/char/Kconfig | 12 | ||||
-rw-r--r-- | drivers/s390/char/Makefile | 3 | ||||
-rw-r--r-- | drivers/s390/char/monwriter.c | 4 | ||||
-rw-r--r-- | drivers/s390/char/raw3270.c | 2 | ||||
-rw-r--r-- | drivers/s390/char/sclp.h | 24 | ||||
-rw-r--r-- | drivers/s390/char/sclp_config.c | 14 | ||||
-rw-r--r-- | drivers/s390/char/sclp_ocf.c | 145 | ||||
-rw-r--r-- | drivers/s390/char/sclp_sdias.c | 3 | ||||
-rw-r--r-- | drivers/s390/char/sclp_tty.c | 122 | ||||
-rw-r--r-- | drivers/s390/char/tape_3590.c | 11 | ||||
-rw-r--r-- | drivers/s390/char/tape_block.c | 444 | ||||
-rw-r--r-- | drivers/s390/char/tape_std.c | 3 | ||||
-rw-r--r-- | drivers/s390/cio/chsc.c | 35 | ||||
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 8 | ||||
-rw-r--r-- | drivers/s390/cio/device_ops.c | 3 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 2 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 8 |
20 files changed, 260 insertions, 600 deletions
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index c64c3807f516..e0b25de1e339 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig | |||
@@ -74,6 +74,8 @@ config ZCRYPT | |||
74 | + PCI-X Cryptographic Coprocessor (PCIXCC) | 74 | + PCI-X Cryptographic Coprocessor (PCIXCC) |
75 | + Crypto Express2 Coprocessor (CEX2C) | 75 | + Crypto Express2 Coprocessor (CEX2C) |
76 | + Crypto Express2 Accelerator (CEX2A) | 76 | + Crypto Express2 Accelerator (CEX2A) |
77 | + Crypto Express3 Coprocessor (CEX3C) | ||
78 | + Crypto Express3 Accelerator (CEX3A) | ||
77 | 79 | ||
78 | config ZCRYPT_MONOLITHIC | 80 | config ZCRYPT_MONOLITHIC |
79 | bool "Monolithic zcrypt module" | 81 | bool "Monolithic zcrypt module" |
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 2b771f18d1ad..c388eda1e2b1 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c | |||
@@ -253,13 +253,11 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
253 | */ | 253 | */ |
254 | void dasd_alias_lcu_setup_complete(struct dasd_device *device) | 254 | void dasd_alias_lcu_setup_complete(struct dasd_device *device) |
255 | { | 255 | { |
256 | struct dasd_eckd_private *private; | ||
257 | unsigned long flags; | 256 | unsigned long flags; |
258 | struct alias_server *server; | 257 | struct alias_server *server; |
259 | struct alias_lcu *lcu; | 258 | struct alias_lcu *lcu; |
260 | struct dasd_uid uid; | 259 | struct dasd_uid uid; |
261 | 260 | ||
262 | private = (struct dasd_eckd_private *) device->private; | ||
263 | device->discipline->get_uid(device, &uid); | 261 | device->discipline->get_uid(device, &uid); |
264 | lcu = NULL; | 262 | lcu = NULL; |
265 | spin_lock_irqsave(&aliastree.lock, flags); | 263 | spin_lock_irqsave(&aliastree.lock, flags); |
@@ -279,13 +277,11 @@ void dasd_alias_lcu_setup_complete(struct dasd_device *device) | |||
279 | 277 | ||
280 | void dasd_alias_wait_for_lcu_setup(struct dasd_device *device) | 278 | void dasd_alias_wait_for_lcu_setup(struct dasd_device *device) |
281 | { | 279 | { |
282 | struct dasd_eckd_private *private; | ||
283 | unsigned long flags; | 280 | unsigned long flags; |
284 | struct alias_server *server; | 281 | struct alias_server *server; |
285 | struct alias_lcu *lcu; | 282 | struct alias_lcu *lcu; |
286 | struct dasd_uid uid; | 283 | struct dasd_uid uid; |
287 | 284 | ||
288 | private = (struct dasd_eckd_private *) device->private; | ||
289 | device->discipline->get_uid(device, &uid); | 285 | device->discipline->get_uid(device, &uid); |
290 | lcu = NULL; | 286 | lcu = NULL; |
291 | spin_lock_irqsave(&aliastree.lock, flags); | 287 | spin_lock_irqsave(&aliastree.lock, flags); |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 3ebdf5f92f8f..30fb979d684d 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -1611,10 +1611,8 @@ static void dasd_eckd_analysis_callback(struct dasd_ccw_req *init_cqr, | |||
1611 | 1611 | ||
1612 | static int dasd_eckd_start_analysis(struct dasd_block *block) | 1612 | static int dasd_eckd_start_analysis(struct dasd_block *block) |
1613 | { | 1613 | { |
1614 | struct dasd_eckd_private *private; | ||
1615 | struct dasd_ccw_req *init_cqr; | 1614 | struct dasd_ccw_req *init_cqr; |
1616 | 1615 | ||
1617 | private = (struct dasd_eckd_private *) block->base->private; | ||
1618 | init_cqr = dasd_eckd_analysis_ccw(block->base); | 1616 | init_cqr = dasd_eckd_analysis_ccw(block->base); |
1619 | if (IS_ERR(init_cqr)) | 1617 | if (IS_ERR(init_cqr)) |
1620 | return PTR_ERR(init_cqr); | 1618 | return PTR_ERR(init_cqr); |
@@ -2264,7 +2262,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( | |||
2264 | unsigned int blk_per_trk, | 2262 | unsigned int blk_per_trk, |
2265 | unsigned int blksize) | 2263 | unsigned int blksize) |
2266 | { | 2264 | { |
2267 | struct dasd_eckd_private *private; | ||
2268 | unsigned long *idaws; | 2265 | unsigned long *idaws; |
2269 | struct dasd_ccw_req *cqr; | 2266 | struct dasd_ccw_req *cqr; |
2270 | struct ccw1 *ccw; | 2267 | struct ccw1 *ccw; |
@@ -2283,7 +2280,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( | |||
2283 | unsigned int recoffs; | 2280 | unsigned int recoffs; |
2284 | 2281 | ||
2285 | basedev = block->base; | 2282 | basedev = block->base; |
2286 | private = (struct dasd_eckd_private *) basedev->private; | ||
2287 | if (rq_data_dir(req) == READ) | 2283 | if (rq_data_dir(req) == READ) |
2288 | cmd = DASD_ECKD_CCW_READ_TRACK_DATA; | 2284 | cmd = DASD_ECKD_CCW_READ_TRACK_DATA; |
2289 | else if (rq_data_dir(req) == WRITE) | 2285 | else if (rq_data_dir(req) == WRITE) |
@@ -2556,8 +2552,7 @@ static int prepare_itcw(struct itcw *itcw, | |||
2556 | 2552 | ||
2557 | dcw = itcw_add_dcw(itcw, pfx_cmd, 0, | 2553 | dcw = itcw_add_dcw(itcw, pfx_cmd, 0, |
2558 | &pfxdata, sizeof(pfxdata), total_data_size); | 2554 | &pfxdata, sizeof(pfxdata), total_data_size); |
2559 | 2555 | return IS_ERR(dcw) ? PTR_ERR(dcw) : 0; | |
2560 | return rc; | ||
2561 | } | 2556 | } |
2562 | 2557 | ||
2563 | static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | 2558 | static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( |
@@ -2573,7 +2568,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
2573 | unsigned int blk_per_trk, | 2568 | unsigned int blk_per_trk, |
2574 | unsigned int blksize) | 2569 | unsigned int blksize) |
2575 | { | 2570 | { |
2576 | struct dasd_eckd_private *private; | ||
2577 | struct dasd_ccw_req *cqr; | 2571 | struct dasd_ccw_req *cqr; |
2578 | struct req_iterator iter; | 2572 | struct req_iterator iter; |
2579 | struct bio_vec *bv; | 2573 | struct bio_vec *bv; |
@@ -2594,7 +2588,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
2594 | unsigned int count, count_to_trk_end; | 2588 | unsigned int count, count_to_trk_end; |
2595 | 2589 | ||
2596 | basedev = block->base; | 2590 | basedev = block->base; |
2597 | private = (struct dasd_eckd_private *) basedev->private; | ||
2598 | if (rq_data_dir(req) == READ) { | 2591 | if (rq_data_dir(req) == READ) { |
2599 | cmd = DASD_ECKD_CCW_READ_TRACK_DATA; | 2592 | cmd = DASD_ECKD_CCW_READ_TRACK_DATA; |
2600 | itcw_op = ITCW_OP_READ; | 2593 | itcw_op = ITCW_OP_READ; |
@@ -2801,7 +2794,6 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev, | |||
2801 | struct dasd_block *block, | 2794 | struct dasd_block *block, |
2802 | struct request *req) | 2795 | struct request *req) |
2803 | { | 2796 | { |
2804 | struct dasd_eckd_private *private; | ||
2805 | unsigned long *idaws; | 2797 | unsigned long *idaws; |
2806 | struct dasd_device *basedev; | 2798 | struct dasd_device *basedev; |
2807 | struct dasd_ccw_req *cqr; | 2799 | struct dasd_ccw_req *cqr; |
@@ -2836,7 +2828,6 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev, | |||
2836 | trkcount = last_trk - first_trk + 1; | 2828 | trkcount = last_trk - first_trk + 1; |
2837 | first_offs = 0; | 2829 | first_offs = 0; |
2838 | basedev = block->base; | 2830 | basedev = block->base; |
2839 | private = (struct dasd_eckd_private *) basedev->private; | ||
2840 | 2831 | ||
2841 | if (rq_data_dir(req) == READ) | 2832 | if (rq_data_dir(req) == READ) |
2842 | cmd = DASD_ECKD_CCW_READ_TRACK; | 2833 | cmd = DASD_ECKD_CCW_READ_TRACK; |
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index dcee3c5c8954..a4f117d9fdc6 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig | |||
@@ -119,18 +119,6 @@ config S390_TAPE | |||
119 | comment "S/390 tape interface support" | 119 | comment "S/390 tape interface support" |
120 | depends on S390_TAPE | 120 | depends on S390_TAPE |
121 | 121 | ||
122 | config S390_TAPE_BLOCK | ||
123 | def_bool y | ||
124 | prompt "Support for tape block devices" | ||
125 | depends on S390_TAPE && BLOCK | ||
126 | help | ||
127 | Select this option if you want to access your channel-attached tape | ||
128 | devices using the block device interface. This interface is similar | ||
129 | to CD-ROM devices on other platforms. The tapes can only be | ||
130 | accessed read-only when using this interface. Have a look at | ||
131 | <file:Documentation/s390/TAPE> for further information about creating | ||
132 | volumes for and using this interface. It is safe to say "Y" here. | ||
133 | |||
134 | comment "S/390 tape hardware support" | 122 | comment "S/390 tape hardware support" |
135 | depends on S390_TAPE | 123 | depends on S390_TAPE |
136 | 124 | ||
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index efb500ab66c0..f3c325207445 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ | 5 | obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ |
6 | sclp_cmd.o sclp_config.o sclp_cpi_sys.o | 6 | sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o |
7 | 7 | ||
8 | obj-$(CONFIG_TN3270) += raw3270.o | 8 | obj-$(CONFIG_TN3270) += raw3270.o |
9 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o | 9 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o |
@@ -22,7 +22,6 @@ obj-$(CONFIG_ZVM_WATCHDOG) += vmwatchdog.o | |||
22 | obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o | 22 | obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o |
23 | obj-$(CONFIG_VMCP) += vmcp.o | 23 | obj-$(CONFIG_VMCP) += vmcp.o |
24 | 24 | ||
25 | tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o | ||
26 | tape-$(CONFIG_PROC_FS) += tape_proc.o | 25 | tape-$(CONFIG_PROC_FS) += tape_proc.o |
27 | tape-objs := tape_core.o tape_std.o tape_char.o $(tape-y) | 26 | tape-objs := tape_core.o tape_std.o tape_char.o $(tape-y) |
28 | obj-$(CONFIG_S390_TAPE) += tape.o tape_class.o | 27 | obj-$(CONFIG_S390_TAPE) += tape.o tape_class.o |
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index e0702d3ea33b..4600aa10a1c6 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c | |||
@@ -97,7 +97,7 @@ static int monwrite_new_hdr(struct mon_private *monpriv) | |||
97 | { | 97 | { |
98 | struct monwrite_hdr *monhdr = &monpriv->hdr; | 98 | struct monwrite_hdr *monhdr = &monpriv->hdr; |
99 | struct mon_buf *monbuf; | 99 | struct mon_buf *monbuf; |
100 | int rc; | 100 | int rc = 0; |
101 | 101 | ||
102 | if (monhdr->datalen > MONWRITE_MAX_DATALEN || | 102 | if (monhdr->datalen > MONWRITE_MAX_DATALEN || |
103 | monhdr->mon_function > MONWRITE_START_CONFIG || | 103 | monhdr->mon_function > MONWRITE_START_CONFIG || |
@@ -135,7 +135,7 @@ static int monwrite_new_hdr(struct mon_private *monpriv) | |||
135 | mon_buf_count++; | 135 | mon_buf_count++; |
136 | } | 136 | } |
137 | monpriv->current_buf = monbuf; | 137 | monpriv->current_buf = monbuf; |
138 | return 0; | 138 | return rc; |
139 | } | 139 | } |
140 | 140 | ||
141 | static int monwrite_new_data(struct mon_private *monpriv) | 141 | static int monwrite_new_data(struct mon_private *monpriv) |
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index e21a5c39ef20..810ac38631c3 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -598,7 +598,6 @@ __raw3270_size_device(struct raw3270 *rp) | |||
598 | static const unsigned char wbuf[] = | 598 | static const unsigned char wbuf[] = |
599 | { 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 }; | 599 | { 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 }; |
600 | struct raw3270_ua *uap; | 600 | struct raw3270_ua *uap; |
601 | unsigned short count; | ||
602 | int rc; | 601 | int rc; |
603 | 602 | ||
604 | /* | 603 | /* |
@@ -653,7 +652,6 @@ __raw3270_size_device(struct raw3270 *rp) | |||
653 | if (rc) | 652 | if (rc) |
654 | return rc; | 653 | return rc; |
655 | /* Got a Query Reply */ | 654 | /* Got a Query Reply */ |
656 | count = sizeof(rp->init_data) - rp->init_request.rescnt; | ||
657 | uap = (struct raw3270_ua *) (rp->init_data + 1); | 655 | uap = (struct raw3270_ua *) (rp->init_data + 1); |
658 | /* Paranoia check. */ | 656 | /* Paranoia check. */ |
659 | if (rp->init_data[0] != 0x88 || uap->uab.qcode != 0x81) | 657 | if (rp->init_data[0] != 0x88 || uap->uab.qcode != 0x81) |
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 6bb5a6bdfab5..49a1bb52bc87 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #define EVTYP_CONFMGMDATA 0x04 | 28 | #define EVTYP_CONFMGMDATA 0x04 |
29 | #define EVTYP_SDIAS 0x1C | 29 | #define EVTYP_SDIAS 0x1C |
30 | #define EVTYP_ASYNC 0x0A | 30 | #define EVTYP_ASYNC 0x0A |
31 | #define EVTYP_OCF 0x1E | ||
31 | 32 | ||
32 | #define EVTYP_OPCMD_MASK 0x80000000 | 33 | #define EVTYP_OPCMD_MASK 0x80000000 |
33 | #define EVTYP_MSG_MASK 0x40000000 | 34 | #define EVTYP_MSG_MASK 0x40000000 |
@@ -40,6 +41,7 @@ | |||
40 | #define EVTYP_CONFMGMDATA_MASK 0x10000000 | 41 | #define EVTYP_CONFMGMDATA_MASK 0x10000000 |
41 | #define EVTYP_SDIAS_MASK 0x00000010 | 42 | #define EVTYP_SDIAS_MASK 0x00000010 |
42 | #define EVTYP_ASYNC_MASK 0x00400000 | 43 | #define EVTYP_ASYNC_MASK 0x00400000 |
44 | #define EVTYP_OCF_MASK 0x00000004 | ||
43 | 45 | ||
44 | #define GNRLMSGFLGS_DOM 0x8000 | 46 | #define GNRLMSGFLGS_DOM 0x8000 |
45 | #define GNRLMSGFLGS_SNDALRM 0x4000 | 47 | #define GNRLMSGFLGS_SNDALRM 0x4000 |
@@ -186,4 +188,26 @@ sclp_ascebc_str(unsigned char *str, int nr) | |||
186 | (MACHINE_IS_VM) ? ASCEBC(str, nr) : ASCEBC_500(str, nr); | 188 | (MACHINE_IS_VM) ? ASCEBC(str, nr) : ASCEBC_500(str, nr); |
187 | } | 189 | } |
188 | 190 | ||
191 | static inline struct gds_vector * | ||
192 | sclp_find_gds_vector(void *start, void *end, u16 id) | ||
193 | { | ||
194 | struct gds_vector *v; | ||
195 | |||
196 | for (v = start; (void *) v < end; v = (void *) v + v->length) | ||
197 | if (v->gds_id == id) | ||
198 | return v; | ||
199 | return NULL; | ||
200 | } | ||
201 | |||
202 | static inline struct gds_subvector * | ||
203 | sclp_find_gds_subvector(void *start, void *end, u8 key) | ||
204 | { | ||
205 | struct gds_subvector *sv; | ||
206 | |||
207 | for (sv = start; (void *) sv < end; sv = (void *) sv + sv->length) | ||
208 | if (sv->key == key) | ||
209 | return sv; | ||
210 | return NULL; | ||
211 | } | ||
212 | |||
189 | #endif /* __SCLP_H__ */ | 213 | #endif /* __SCLP_H__ */ |
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c index 16e232a99fb7..95b909ac2b73 100644 --- a/drivers/s390/char/sclp_config.c +++ b/drivers/s390/char/sclp_config.c | |||
@@ -71,21 +71,9 @@ static struct sclp_register sclp_conf_register = | |||
71 | 71 | ||
72 | static int __init sclp_conf_init(void) | 72 | static int __init sclp_conf_init(void) |
73 | { | 73 | { |
74 | int rc; | ||
75 | |||
76 | INIT_WORK(&sclp_cpu_capability_work, sclp_cpu_capability_notify); | 74 | INIT_WORK(&sclp_cpu_capability_work, sclp_cpu_capability_notify); |
77 | INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify); | 75 | INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify); |
78 | 76 | return sclp_register(&sclp_conf_register); | |
79 | rc = sclp_register(&sclp_conf_register); | ||
80 | if (rc) | ||
81 | return rc; | ||
82 | |||
83 | if (!(sclp_conf_register.sclp_send_mask & EVTYP_CONFMGMDATA_MASK)) { | ||
84 | pr_warning("no configuration management.\n"); | ||
85 | sclp_unregister(&sclp_conf_register); | ||
86 | rc = -ENOSYS; | ||
87 | } | ||
88 | return rc; | ||
89 | } | 77 | } |
90 | 78 | ||
91 | __initcall(sclp_conf_init); | 79 | __initcall(sclp_conf_init); |
diff --git a/drivers/s390/char/sclp_ocf.c b/drivers/s390/char/sclp_ocf.c new file mode 100644 index 000000000000..ab294d5a534e --- /dev/null +++ b/drivers/s390/char/sclp_ocf.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * drivers/s390/char/sclp_ocf.c | ||
3 | * SCLP OCF communication parameters sysfs interface | ||
4 | * | ||
5 | * Copyright IBM Corp. 2011 | ||
6 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
7 | */ | ||
8 | |||
9 | #define KMSG_COMPONENT "sclp_ocf" | ||
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/stat.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/ctype.h> | ||
18 | #include <linux/kmod.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <asm/ebcdic.h> | ||
22 | #include <asm/sclp.h> | ||
23 | |||
24 | #include "sclp.h" | ||
25 | |||
26 | #define OCF_LENGTH_HMC_NETWORK 8UL | ||
27 | #define OCF_LENGTH_CPC_NAME 8UL | ||
28 | |||
29 | static char hmc_network[OCF_LENGTH_HMC_NETWORK + 1]; | ||
30 | static char cpc_name[OCF_LENGTH_CPC_NAME + 1]; | ||
31 | |||
32 | static DEFINE_SPINLOCK(sclp_ocf_lock); | ||
33 | static struct work_struct sclp_ocf_change_work; | ||
34 | |||
35 | static struct kset *ocf_kset; | ||
36 | |||
37 | static void sclp_ocf_change_notify(struct work_struct *work) | ||
38 | { | ||
39 | kobject_uevent(&ocf_kset->kobj, KOBJ_CHANGE); | ||
40 | } | ||
41 | |||
42 | /* Handler for OCF event. Look for the CPC image name. */ | ||
43 | static void sclp_ocf_handler(struct evbuf_header *evbuf) | ||
44 | { | ||
45 | struct gds_vector *v; | ||
46 | struct gds_subvector *sv, *netid, *cpc; | ||
47 | size_t size; | ||
48 | |||
49 | /* Find the 0x9f00 block. */ | ||
50 | v = sclp_find_gds_vector(evbuf + 1, (void *) evbuf + evbuf->length, | ||
51 | 0x9f00); | ||
52 | if (!v) | ||
53 | return; | ||
54 | /* Find the 0x9f22 block inside the 0x9f00 block. */ | ||
55 | v = sclp_find_gds_vector(v + 1, (void *) v + v->length, 0x9f22); | ||
56 | if (!v) | ||
57 | return; | ||
58 | /* Find the 0x81 block inside the 0x9f22 block. */ | ||
59 | sv = sclp_find_gds_subvector(v + 1, (void *) v + v->length, 0x81); | ||
60 | if (!sv) | ||
61 | return; | ||
62 | /* Find the 0x01 block inside the 0x81 block. */ | ||
63 | netid = sclp_find_gds_subvector(sv + 1, (void *) sv + sv->length, 1); | ||
64 | /* Find the 0x02 block inside the 0x81 block. */ | ||
65 | cpc = sclp_find_gds_subvector(sv + 1, (void *) sv + sv->length, 2); | ||
66 | /* Copy network name and cpc name. */ | ||
67 | spin_lock(&sclp_ocf_lock); | ||
68 | if (netid) { | ||
69 | size = min(OCF_LENGTH_HMC_NETWORK, (size_t) netid->length); | ||
70 | memcpy(hmc_network, netid + 1, size); | ||
71 | EBCASC(hmc_network, size); | ||
72 | hmc_network[size] = 0; | ||
73 | } | ||
74 | if (cpc) { | ||
75 | size = min(OCF_LENGTH_CPC_NAME, (size_t) cpc->length); | ||
76 | memcpy(cpc_name, cpc + 1, size); | ||
77 | EBCASC(cpc_name, size); | ||
78 | cpc_name[size] = 0; | ||
79 | } | ||
80 | spin_unlock(&sclp_ocf_lock); | ||
81 | schedule_work(&sclp_ocf_change_work); | ||
82 | } | ||
83 | |||
84 | static struct sclp_register sclp_ocf_event = { | ||
85 | .receive_mask = EVTYP_OCF_MASK, | ||
86 | .receiver_fn = sclp_ocf_handler, | ||
87 | }; | ||
88 | |||
89 | static ssize_t cpc_name_show(struct kobject *kobj, | ||
90 | struct kobj_attribute *attr, char *page) | ||
91 | { | ||
92 | int rc; | ||
93 | |||
94 | spin_lock_irq(&sclp_ocf_lock); | ||
95 | rc = snprintf(page, PAGE_SIZE, "%s\n", cpc_name); | ||
96 | spin_unlock_irq(&sclp_ocf_lock); | ||
97 | return rc; | ||
98 | } | ||
99 | |||
100 | static struct kobj_attribute cpc_name_attr = | ||
101 | __ATTR(cpc_name, 0444, cpc_name_show, NULL); | ||
102 | |||
103 | static ssize_t hmc_network_show(struct kobject *kobj, | ||
104 | struct kobj_attribute *attr, char *page) | ||
105 | { | ||
106 | int rc; | ||
107 | |||
108 | spin_lock_irq(&sclp_ocf_lock); | ||
109 | rc = snprintf(page, PAGE_SIZE, "%s\n", hmc_network); | ||
110 | spin_unlock_irq(&sclp_ocf_lock); | ||
111 | return rc; | ||
112 | } | ||
113 | |||
114 | static struct kobj_attribute hmc_network_attr = | ||
115 | __ATTR(hmc_network, 0444, hmc_network_show, NULL); | ||
116 | |||
117 | static struct attribute *ocf_attrs[] = { | ||
118 | &cpc_name_attr.attr, | ||
119 | &hmc_network_attr.attr, | ||
120 | NULL, | ||
121 | }; | ||
122 | |||
123 | static struct attribute_group ocf_attr_group = { | ||
124 | .attrs = ocf_attrs, | ||
125 | }; | ||
126 | |||
127 | static int __init ocf_init(void) | ||
128 | { | ||
129 | int rc; | ||
130 | |||
131 | INIT_WORK(&sclp_ocf_change_work, sclp_ocf_change_notify); | ||
132 | ocf_kset = kset_create_and_add("ocf", NULL, firmware_kobj); | ||
133 | if (!ocf_kset) | ||
134 | return -ENOMEM; | ||
135 | |||
136 | rc = sysfs_create_group(&ocf_kset->kobj, &ocf_attr_group); | ||
137 | if (rc) { | ||
138 | kset_unregister(ocf_kset); | ||
139 | return rc; | ||
140 | } | ||
141 | |||
142 | return sclp_register(&sclp_ocf_event); | ||
143 | } | ||
144 | |||
145 | device_initcall(ocf_init); | ||
diff --git a/drivers/s390/char/sclp_sdias.c b/drivers/s390/char/sclp_sdias.c index 6a1c58dc61a7..fa733ecd3d70 100644 --- a/drivers/s390/char/sclp_sdias.c +++ b/drivers/s390/char/sclp_sdias.c | |||
@@ -69,9 +69,6 @@ static DEFINE_MUTEX(sdias_mutex); | |||
69 | 69 | ||
70 | static void sdias_callback(struct sclp_req *request, void *data) | 70 | static void sdias_callback(struct sclp_req *request, void *data) |
71 | { | 71 | { |
72 | struct sdias_sccb *cbsccb; | ||
73 | |||
74 | cbsccb = (struct sdias_sccb *) request->sccb; | ||
75 | sclp_req_done = 1; | 72 | sclp_req_done = 1; |
76 | wake_up(&sdias_wq); /* Inform caller, that request is complete */ | 73 | wake_up(&sdias_wq); /* Inform caller, that request is complete */ |
77 | TRACE("callback done\n"); | 74 | TRACE("callback done\n"); |
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 8258d590505f..a879c139926a 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c | |||
@@ -408,118 +408,72 @@ static int sclp_switch_cases(unsigned char *buf, int count) | |||
408 | return op - buf; | 408 | return op - buf; |
409 | } | 409 | } |
410 | 410 | ||
411 | static void | 411 | static void sclp_get_input(struct gds_subvector *sv) |
412 | sclp_get_input(unsigned char *start, unsigned char *end) | ||
413 | { | 412 | { |
413 | unsigned char *str; | ||
414 | int count; | 414 | int count; |
415 | 415 | ||
416 | count = end - start; | 416 | str = (unsigned char *) (sv + 1); |
417 | count = sv->length - sizeof(*sv); | ||
417 | if (sclp_tty_tolower) | 418 | if (sclp_tty_tolower) |
418 | EBC_TOLOWER(start, count); | 419 | EBC_TOLOWER(str, count); |
419 | count = sclp_switch_cases(start, count); | 420 | count = sclp_switch_cases(str, count); |
420 | /* convert EBCDIC to ASCII (modify original input in SCCB) */ | 421 | /* convert EBCDIC to ASCII (modify original input in SCCB) */ |
421 | sclp_ebcasc_str(start, count); | 422 | sclp_ebcasc_str(str, count); |
422 | 423 | ||
423 | /* transfer input to high level driver */ | 424 | /* transfer input to high level driver */ |
424 | sclp_tty_input(start, count); | 425 | sclp_tty_input(str, count); |
425 | } | ||
426 | |||
427 | static inline struct gds_vector * | ||
428 | find_gds_vector(struct gds_vector *start, struct gds_vector *end, u16 id) | ||
429 | { | ||
430 | struct gds_vector *vec; | ||
431 | |||
432 | for (vec = start; vec < end; vec = (void *) vec + vec->length) | ||
433 | if (vec->gds_id == id) | ||
434 | return vec; | ||
435 | return NULL; | ||
436 | } | 426 | } |
437 | 427 | ||
438 | static inline struct gds_subvector * | 428 | static inline void sclp_eval_selfdeftextmsg(struct gds_subvector *sv) |
439 | find_gds_subvector(struct gds_subvector *start, | ||
440 | struct gds_subvector *end, u8 key) | ||
441 | { | 429 | { |
442 | struct gds_subvector *subvec; | 430 | void *end; |
443 | 431 | ||
444 | for (subvec = start; subvec < end; | 432 | end = (void *) sv + sv->length; |
445 | subvec = (void *) subvec + subvec->length) | 433 | for (sv = sv + 1; (void *) sv < end; sv = (void *) sv + sv->length) |
446 | if (subvec->key == key) | 434 | if (sv->key == 0x30) |
447 | return subvec; | 435 | sclp_get_input(sv); |
448 | return NULL; | ||
449 | } | 436 | } |
450 | 437 | ||
451 | static inline void | 438 | static inline void sclp_eval_textcmd(struct gds_vector *v) |
452 | sclp_eval_selfdeftextmsg(struct gds_subvector *start, | ||
453 | struct gds_subvector *end) | ||
454 | { | 439 | { |
455 | struct gds_subvector *subvec; | 440 | struct gds_subvector *sv; |
456 | 441 | void *end; | |
457 | subvec = start; | ||
458 | while (subvec < end) { | ||
459 | subvec = find_gds_subvector(subvec, end, 0x30); | ||
460 | if (!subvec) | ||
461 | break; | ||
462 | sclp_get_input((unsigned char *)(subvec + 1), | ||
463 | (unsigned char *) subvec + subvec->length); | ||
464 | subvec = (void *) subvec + subvec->length; | ||
465 | } | ||
466 | } | ||
467 | 442 | ||
468 | static inline void | 443 | end = (void *) v + v->length; |
469 | sclp_eval_textcmd(struct gds_subvector *start, | 444 | for (sv = (struct gds_subvector *) (v + 1); |
470 | struct gds_subvector *end) | 445 | (void *) sv < end; sv = (void *) sv + sv->length) |
471 | { | 446 | if (sv->key == GDS_KEY_SELFDEFTEXTMSG) |
472 | struct gds_subvector *subvec; | 447 | sclp_eval_selfdeftextmsg(sv); |
473 | 448 | ||
474 | subvec = start; | ||
475 | while (subvec < end) { | ||
476 | subvec = find_gds_subvector(subvec, end, | ||
477 | GDS_KEY_SELFDEFTEXTMSG); | ||
478 | if (!subvec) | ||
479 | break; | ||
480 | sclp_eval_selfdeftextmsg((struct gds_subvector *)(subvec + 1), | ||
481 | (void *)subvec + subvec->length); | ||
482 | subvec = (void *) subvec + subvec->length; | ||
483 | } | ||
484 | } | 449 | } |
485 | 450 | ||
486 | static inline void | 451 | static inline void sclp_eval_cpmsu(struct gds_vector *v) |
487 | sclp_eval_cpmsu(struct gds_vector *start, struct gds_vector *end) | ||
488 | { | 452 | { |
489 | struct gds_vector *vec; | 453 | void *end; |
490 | 454 | ||
491 | vec = start; | 455 | end = (void *) v + v->length; |
492 | while (vec < end) { | 456 | for (v = v + 1; (void *) v < end; v = (void *) v + v->length) |
493 | vec = find_gds_vector(vec, end, GDS_ID_TEXTCMD); | 457 | if (v->gds_id == GDS_ID_TEXTCMD) |
494 | if (!vec) | 458 | sclp_eval_textcmd(v); |
495 | break; | ||
496 | sclp_eval_textcmd((struct gds_subvector *)(vec + 1), | ||
497 | (void *) vec + vec->length); | ||
498 | vec = (void *) vec + vec->length; | ||
499 | } | ||
500 | } | 459 | } |
501 | 460 | ||
502 | 461 | ||
503 | static inline void | 462 | static inline void sclp_eval_mdsmu(struct gds_vector *v) |
504 | sclp_eval_mdsmu(struct gds_vector *start, void *end) | ||
505 | { | 463 | { |
506 | struct gds_vector *vec; | 464 | v = sclp_find_gds_vector(v + 1, (void *) v + v->length, GDS_ID_CPMSU); |
507 | 465 | if (v) | |
508 | vec = find_gds_vector(start, end, GDS_ID_CPMSU); | 466 | sclp_eval_cpmsu(v); |
509 | if (vec) | ||
510 | sclp_eval_cpmsu(vec + 1, (void *) vec + vec->length); | ||
511 | } | 467 | } |
512 | 468 | ||
513 | static void | 469 | static void sclp_tty_receiver(struct evbuf_header *evbuf) |
514 | sclp_tty_receiver(struct evbuf_header *evbuf) | ||
515 | { | 470 | { |
516 | struct gds_vector *start, *end, *vec; | 471 | struct gds_vector *v; |
517 | 472 | ||
518 | start = (struct gds_vector *)(evbuf + 1); | 473 | v = sclp_find_gds_vector(evbuf + 1, (void *) evbuf + evbuf->length, |
519 | end = (void *) evbuf + evbuf->length; | 474 | GDS_ID_MDSMU); |
520 | vec = find_gds_vector(start, end, GDS_ID_MDSMU); | 475 | if (v) |
521 | if (vec) | 476 | sclp_eval_mdsmu(v); |
522 | sclp_eval_mdsmu(vec + 1, (void *) vec + vec->length); | ||
523 | } | 477 | } |
524 | 478 | ||
525 | static void | 479 | static void |
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index b98dcbd16711..a7d570728882 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -796,10 +796,8 @@ static void tape_3590_med_state_set(struct tape_device *device, | |||
796 | static int | 796 | static int |
797 | tape_3590_done(struct tape_device *device, struct tape_request *request) | 797 | tape_3590_done(struct tape_device *device, struct tape_request *request) |
798 | { | 798 | { |
799 | struct tape_3590_disc_data *disc_data; | ||
800 | 799 | ||
801 | DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]); | 800 | DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]); |
802 | disc_data = device->discdata; | ||
803 | 801 | ||
804 | switch (request->op) { | 802 | switch (request->op) { |
805 | case TO_BSB: | 803 | case TO_BSB: |
@@ -1394,17 +1392,12 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) | |||
1394 | static int tape_3590_crypt_error(struct tape_device *device, | 1392 | static int tape_3590_crypt_error(struct tape_device *device, |
1395 | struct tape_request *request, struct irb *irb) | 1393 | struct tape_request *request, struct irb *irb) |
1396 | { | 1394 | { |
1397 | u8 cu_rc, ekm_rc1; | 1395 | u8 cu_rc; |
1398 | u16 ekm_rc2; | 1396 | u16 ekm_rc2; |
1399 | u32 drv_rc; | ||
1400 | const char *bus_id; | ||
1401 | char *sense; | 1397 | char *sense; |
1402 | 1398 | ||
1403 | sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data; | 1399 | sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data; |
1404 | bus_id = dev_name(&device->cdev->dev); | ||
1405 | cu_rc = sense[0]; | 1400 | cu_rc = sense[0]; |
1406 | drv_rc = *((u32*) &sense[5]) & 0xffffff; | ||
1407 | ekm_rc1 = sense[9]; | ||
1408 | ekm_rc2 = *((u16*) &sense[10]); | 1401 | ekm_rc2 = *((u16*) &sense[10]); |
1409 | if ((cu_rc == 0) && (ekm_rc2 == 0xee31)) | 1402 | if ((cu_rc == 0) && (ekm_rc2 == 0xee31)) |
1410 | /* key not defined on EKM */ | 1403 | /* key not defined on EKM */ |
@@ -1429,7 +1422,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, | |||
1429 | struct irb *irb) | 1422 | struct irb *irb) |
1430 | { | 1423 | { |
1431 | struct tape_3590_sense *sense; | 1424 | struct tape_3590_sense *sense; |
1432 | int rc; | ||
1433 | 1425 | ||
1434 | #ifdef CONFIG_S390_TAPE_BLOCK | 1426 | #ifdef CONFIG_S390_TAPE_BLOCK |
1435 | if (request->op == TO_BLOCK) { | 1427 | if (request->op == TO_BLOCK) { |
@@ -1454,7 +1446,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, | |||
1454 | * - "break": basic error recovery is done | 1446 | * - "break": basic error recovery is done |
1455 | * - "goto out:": just print error message if available | 1447 | * - "goto out:": just print error message if available |
1456 | */ | 1448 | */ |
1457 | rc = -EIO; | ||
1458 | switch (sense->rc_rqc) { | 1449 | switch (sense->rc_rqc) { |
1459 | 1450 | ||
1460 | case 0x1110: | 1451 | case 0x1110: |
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c deleted file mode 100644 index 1b3924c2fffd..000000000000 --- a/drivers/s390/char/tape_block.c +++ /dev/null | |||
@@ -1,444 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/s390/char/tape_block.c | ||
3 | * block device frontend for tape device driver | ||
4 | * | ||
5 | * S390 and zSeries version | ||
6 | * Copyright (C) 2001,2003 IBM Deutschland Entwicklung GmbH, IBM Corporation | ||
7 | * Author(s): Carsten Otte <cotte@de.ibm.com> | ||
8 | * Tuan Ngo-Anh <ngoanh@de.ibm.com> | ||
9 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
10 | * Stefan Bader <shbader@de.ibm.com> | ||
11 | */ | ||
12 | |||
13 | #define KMSG_COMPONENT "tape" | ||
14 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
15 | |||
16 | #include <linux/fs.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/blkdev.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/buffer_head.h> | ||
22 | #include <linux/kernel.h> | ||
23 | |||
24 | #include <asm/debug.h> | ||
25 | |||
26 | #define TAPE_DBF_AREA tape_core_dbf | ||
27 | |||
28 | #include "tape.h" | ||
29 | |||
30 | #define TAPEBLOCK_MAX_SEC 100 | ||
31 | #define TAPEBLOCK_MIN_REQUEUE 3 | ||
32 | |||
33 | /* | ||
34 | * 2003/11/25 Stefan Bader <shbader@de.ibm.com> | ||
35 | * | ||
36 | * In 2.5/2.6 the block device request function is very likely to be called | ||
37 | * with disabled interrupts (e.g. generic_unplug_device). So the driver can't | ||
38 | * just call any function that tries to allocate CCW requests from that con- | ||
39 | * text since it might sleep. There are two choices to work around this: | ||
40 | * a) do not allocate with kmalloc but use its own memory pool | ||
41 | * b) take requests from the queue outside that context, knowing that | ||
42 | * allocation might sleep | ||
43 | */ | ||
44 | |||
45 | /* | ||
46 | * file operation structure for tape block frontend | ||
47 | */ | ||
48 | static DEFINE_MUTEX(tape_block_mutex); | ||
49 | static int tapeblock_open(struct block_device *, fmode_t); | ||
50 | static int tapeblock_release(struct gendisk *, fmode_t); | ||
51 | static unsigned int tapeblock_check_events(struct gendisk *, unsigned int); | ||
52 | static int tapeblock_revalidate_disk(struct gendisk *); | ||
53 | |||
54 | static const struct block_device_operations tapeblock_fops = { | ||
55 | .owner = THIS_MODULE, | ||
56 | .open = tapeblock_open, | ||
57 | .release = tapeblock_release, | ||
58 | .check_events = tapeblock_check_events, | ||
59 | .revalidate_disk = tapeblock_revalidate_disk, | ||
60 | }; | ||
61 | |||
62 | static int tapeblock_major = 0; | ||
63 | |||
64 | static void | ||
65 | tapeblock_trigger_requeue(struct tape_device *device) | ||
66 | { | ||
67 | /* Protect against rescheduling. */ | ||
68 | if (atomic_cmpxchg(&device->blk_data.requeue_scheduled, 0, 1) != 0) | ||
69 | return; | ||
70 | schedule_work(&device->blk_data.requeue_task); | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Post finished request. | ||
75 | */ | ||
76 | static void | ||
77 | __tapeblock_end_request(struct tape_request *ccw_req, void *data) | ||
78 | { | ||
79 | struct tape_device *device; | ||
80 | struct request *req; | ||
81 | |||
82 | DBF_LH(6, "__tapeblock_end_request()\n"); | ||
83 | |||
84 | device = ccw_req->device; | ||
85 | req = (struct request *) data; | ||
86 | blk_end_request_all(req, (ccw_req->rc == 0) ? 0 : -EIO); | ||
87 | if (ccw_req->rc == 0) | ||
88 | /* Update position. */ | ||
89 | device->blk_data.block_position = | ||
90 | (blk_rq_pos(req) + blk_rq_sectors(req)) >> TAPEBLOCK_HSEC_S2B; | ||
91 | else | ||
92 | /* We lost the position information due to an error. */ | ||
93 | device->blk_data.block_position = -1; | ||
94 | device->discipline->free_bread(ccw_req); | ||
95 | if (!list_empty(&device->req_queue) || | ||
96 | blk_peek_request(device->blk_data.request_queue)) | ||
97 | tapeblock_trigger_requeue(device); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * Feed the tape device CCW queue with requests supplied in a list. | ||
102 | */ | ||
103 | static int | ||
104 | tapeblock_start_request(struct tape_device *device, struct request *req) | ||
105 | { | ||
106 | struct tape_request * ccw_req; | ||
107 | int rc; | ||
108 | |||
109 | DBF_LH(6, "tapeblock_start_request(%p, %p)\n", device, req); | ||
110 | |||
111 | ccw_req = device->discipline->bread(device, req); | ||
112 | if (IS_ERR(ccw_req)) { | ||
113 | DBF_EVENT(1, "TBLOCK: bread failed\n"); | ||
114 | blk_end_request_all(req, -EIO); | ||
115 | return PTR_ERR(ccw_req); | ||
116 | } | ||
117 | ccw_req->callback = __tapeblock_end_request; | ||
118 | ccw_req->callback_data = (void *) req; | ||
119 | ccw_req->retries = TAPEBLOCK_RETRIES; | ||
120 | |||
121 | rc = tape_do_io_async(device, ccw_req); | ||
122 | if (rc) { | ||
123 | /* | ||
124 | * Start/enqueueing failed. No retries in | ||
125 | * this case. | ||
126 | */ | ||
127 | blk_end_request_all(req, -EIO); | ||
128 | device->discipline->free_bread(ccw_req); | ||
129 | } | ||
130 | |||
131 | return rc; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Move requests from the block device request queue to the tape device ccw | ||
136 | * queue. | ||
137 | */ | ||
138 | static void | ||
139 | tapeblock_requeue(struct work_struct *work) { | ||
140 | struct tape_blk_data * blkdat; | ||
141 | struct tape_device * device; | ||
142 | struct request_queue * queue; | ||
143 | int nr_queued; | ||
144 | struct request * req; | ||
145 | struct list_head * l; | ||
146 | int rc; | ||
147 | |||
148 | blkdat = container_of(work, struct tape_blk_data, requeue_task); | ||
149 | device = blkdat->device; | ||
150 | if (!device) | ||
151 | return; | ||
152 | |||
153 | spin_lock_irq(get_ccwdev_lock(device->cdev)); | ||
154 | queue = device->blk_data.request_queue; | ||
155 | |||
156 | /* Count number of requests on ccw queue. */ | ||
157 | nr_queued = 0; | ||
158 | list_for_each(l, &device->req_queue) | ||
159 | nr_queued++; | ||
160 | spin_unlock(get_ccwdev_lock(device->cdev)); | ||
161 | |||
162 | spin_lock_irq(&device->blk_data.request_queue_lock); | ||
163 | while ( | ||
164 | blk_peek_request(queue) && | ||
165 | nr_queued < TAPEBLOCK_MIN_REQUEUE | ||
166 | ) { | ||
167 | req = blk_fetch_request(queue); | ||
168 | if (rq_data_dir(req) == WRITE) { | ||
169 | DBF_EVENT(1, "TBLOCK: Rejecting write request\n"); | ||
170 | spin_unlock_irq(&device->blk_data.request_queue_lock); | ||
171 | blk_end_request_all(req, -EIO); | ||
172 | spin_lock_irq(&device->blk_data.request_queue_lock); | ||
173 | continue; | ||
174 | } | ||
175 | nr_queued++; | ||
176 | spin_unlock_irq(&device->blk_data.request_queue_lock); | ||
177 | rc = tapeblock_start_request(device, req); | ||
178 | spin_lock_irq(&device->blk_data.request_queue_lock); | ||
179 | } | ||
180 | spin_unlock_irq(&device->blk_data.request_queue_lock); | ||
181 | atomic_set(&device->blk_data.requeue_scheduled, 0); | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * Tape request queue function. Called from ll_rw_blk.c | ||
186 | */ | ||
187 | static void | ||
188 | tapeblock_request_fn(struct request_queue *queue) | ||
189 | { | ||
190 | struct tape_device *device; | ||
191 | |||
192 | device = (struct tape_device *) queue->queuedata; | ||
193 | DBF_LH(6, "tapeblock_request_fn(device=%p)\n", device); | ||
194 | BUG_ON(device == NULL); | ||
195 | tapeblock_trigger_requeue(device); | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * This function is called for every new tapedevice | ||
200 | */ | ||
201 | int | ||
202 | tapeblock_setup_device(struct tape_device * device) | ||
203 | { | ||
204 | struct tape_blk_data * blkdat; | ||
205 | struct gendisk * disk; | ||
206 | int rc; | ||
207 | |||
208 | blkdat = &device->blk_data; | ||
209 | blkdat->device = device; | ||
210 | spin_lock_init(&blkdat->request_queue_lock); | ||
211 | atomic_set(&blkdat->requeue_scheduled, 0); | ||
212 | |||
213 | blkdat->request_queue = blk_init_queue( | ||
214 | tapeblock_request_fn, | ||
215 | &blkdat->request_queue_lock | ||
216 | ); | ||
217 | if (!blkdat->request_queue) | ||
218 | return -ENOMEM; | ||
219 | |||
220 | rc = elevator_change(blkdat->request_queue, "noop"); | ||
221 | if (rc) | ||
222 | goto cleanup_queue; | ||
223 | |||
224 | blk_queue_logical_block_size(blkdat->request_queue, TAPEBLOCK_HSEC_SIZE); | ||
225 | blk_queue_max_hw_sectors(blkdat->request_queue, TAPEBLOCK_MAX_SEC); | ||
226 | blk_queue_max_segments(blkdat->request_queue, -1L); | ||
227 | blk_queue_max_segment_size(blkdat->request_queue, -1L); | ||
228 | blk_queue_segment_boundary(blkdat->request_queue, -1L); | ||
229 | |||
230 | disk = alloc_disk(1); | ||
231 | if (!disk) { | ||
232 | rc = -ENOMEM; | ||
233 | goto cleanup_queue; | ||
234 | } | ||
235 | |||
236 | disk->major = tapeblock_major; | ||
237 | disk->first_minor = device->first_minor; | ||
238 | disk->fops = &tapeblock_fops; | ||
239 | disk->private_data = tape_get_device(device); | ||
240 | disk->queue = blkdat->request_queue; | ||
241 | set_capacity(disk, 0); | ||
242 | sprintf(disk->disk_name, "btibm%d", | ||
243 | device->first_minor / TAPE_MINORS_PER_DEV); | ||
244 | |||
245 | blkdat->disk = disk; | ||
246 | blkdat->medium_changed = 1; | ||
247 | blkdat->request_queue->queuedata = tape_get_device(device); | ||
248 | |||
249 | add_disk(disk); | ||
250 | |||
251 | tape_get_device(device); | ||
252 | INIT_WORK(&blkdat->requeue_task, tapeblock_requeue); | ||
253 | |||
254 | return 0; | ||
255 | |||
256 | cleanup_queue: | ||
257 | blk_cleanup_queue(blkdat->request_queue); | ||
258 | blkdat->request_queue = NULL; | ||
259 | |||
260 | return rc; | ||
261 | } | ||
262 | |||
263 | void | ||
264 | tapeblock_cleanup_device(struct tape_device *device) | ||
265 | { | ||
266 | flush_work_sync(&device->blk_data.requeue_task); | ||
267 | tape_put_device(device); | ||
268 | |||
269 | if (!device->blk_data.disk) { | ||
270 | goto cleanup_queue; | ||
271 | } | ||
272 | |||
273 | del_gendisk(device->blk_data.disk); | ||
274 | device->blk_data.disk->private_data = NULL; | ||
275 | tape_put_device(device); | ||
276 | put_disk(device->blk_data.disk); | ||
277 | |||
278 | device->blk_data.disk = NULL; | ||
279 | cleanup_queue: | ||
280 | device->blk_data.request_queue->queuedata = NULL; | ||
281 | tape_put_device(device); | ||
282 | |||
283 | blk_cleanup_queue(device->blk_data.request_queue); | ||
284 | device->blk_data.request_queue = NULL; | ||
285 | } | ||
286 | |||
287 | /* | ||
288 | * Detect number of blocks of the tape. | ||
289 | * FIXME: can we extent this to detect the blocks size as well ? | ||
290 | */ | ||
291 | static int | ||
292 | tapeblock_revalidate_disk(struct gendisk *disk) | ||
293 | { | ||
294 | struct tape_device * device; | ||
295 | unsigned int nr_of_blks; | ||
296 | int rc; | ||
297 | |||
298 | device = (struct tape_device *) disk->private_data; | ||
299 | BUG_ON(!device); | ||
300 | |||
301 | if (!device->blk_data.medium_changed) | ||
302 | return 0; | ||
303 | |||
304 | rc = tape_mtop(device, MTFSFM, 1); | ||
305 | if (rc) | ||
306 | return rc; | ||
307 | |||
308 | rc = tape_mtop(device, MTTELL, 1); | ||
309 | if (rc < 0) | ||
310 | return rc; | ||
311 | |||
312 | pr_info("%s: Determining the size of the recorded area...\n", | ||
313 | dev_name(&device->cdev->dev)); | ||
314 | DBF_LH(3, "Image file ends at %d\n", rc); | ||
315 | nr_of_blks = rc; | ||
316 | |||
317 | /* This will fail for the first file. Catch the error by checking the | ||
318 | * position. */ | ||
319 | tape_mtop(device, MTBSF, 1); | ||
320 | |||
321 | rc = tape_mtop(device, MTTELL, 1); | ||
322 | if (rc < 0) | ||
323 | return rc; | ||
324 | |||
325 | if (rc > nr_of_blks) | ||
326 | return -EINVAL; | ||
327 | |||
328 | DBF_LH(3, "Image file starts at %d\n", rc); | ||
329 | device->bof = rc; | ||
330 | nr_of_blks -= rc; | ||
331 | |||
332 | pr_info("%s: The size of the recorded area is %i blocks\n", | ||
333 | dev_name(&device->cdev->dev), nr_of_blks); | ||
334 | set_capacity(device->blk_data.disk, | ||
335 | nr_of_blks*(TAPEBLOCK_HSEC_SIZE/512)); | ||
336 | |||
337 | device->blk_data.block_position = 0; | ||
338 | device->blk_data.medium_changed = 0; | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static unsigned int | ||
343 | tapeblock_check_events(struct gendisk *disk, unsigned int clearing) | ||
344 | { | ||
345 | struct tape_device *device; | ||
346 | |||
347 | device = (struct tape_device *) disk->private_data; | ||
348 | DBF_LH(6, "tapeblock_medium_changed(%p) = %d\n", | ||
349 | device, device->blk_data.medium_changed); | ||
350 | |||
351 | return device->blk_data.medium_changed ? DISK_EVENT_MEDIA_CHANGE : 0; | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * Block frontend tape device open function. | ||
356 | */ | ||
357 | static int | ||
358 | tapeblock_open(struct block_device *bdev, fmode_t mode) | ||
359 | { | ||
360 | struct gendisk * disk = bdev->bd_disk; | ||
361 | struct tape_device * device; | ||
362 | int rc; | ||
363 | |||
364 | mutex_lock(&tape_block_mutex); | ||
365 | device = tape_get_device(disk->private_data); | ||
366 | |||
367 | if (device->required_tapemarks) { | ||
368 | DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); | ||
369 | pr_warning("%s: Opening the tape failed because of missing " | ||
370 | "end-of-file marks\n", dev_name(&device->cdev->dev)); | ||
371 | rc = -EPERM; | ||
372 | goto put_device; | ||
373 | } | ||
374 | |||
375 | rc = tape_open(device); | ||
376 | if (rc) | ||
377 | goto put_device; | ||
378 | |||
379 | rc = tapeblock_revalidate_disk(disk); | ||
380 | if (rc) | ||
381 | goto release; | ||
382 | |||
383 | /* | ||
384 | * Note: The reference to <device> is hold until the release function | ||
385 | * is called. | ||
386 | */ | ||
387 | tape_state_set(device, TS_BLKUSE); | ||
388 | mutex_unlock(&tape_block_mutex); | ||
389 | return 0; | ||
390 | |||
391 | release: | ||
392 | tape_release(device); | ||
393 | put_device: | ||
394 | tape_put_device(device); | ||
395 | mutex_unlock(&tape_block_mutex); | ||
396 | return rc; | ||
397 | } | ||
398 | |||
399 | /* | ||
400 | * Block frontend tape device release function. | ||
401 | * | ||
402 | * Note: One reference to the tape device was made by the open function. So | ||
403 | * we just get the pointer here and release the reference. | ||
404 | */ | ||
405 | static int | ||
406 | tapeblock_release(struct gendisk *disk, fmode_t mode) | ||
407 | { | ||
408 | struct tape_device *device = disk->private_data; | ||
409 | |||
410 | mutex_lock(&tape_block_mutex); | ||
411 | tape_state_set(device, TS_IN_USE); | ||
412 | tape_release(device); | ||
413 | tape_put_device(device); | ||
414 | mutex_unlock(&tape_block_mutex); | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * Initialize block device frontend. | ||
421 | */ | ||
422 | int | ||
423 | tapeblock_init(void) | ||
424 | { | ||
425 | int rc; | ||
426 | |||
427 | /* Register the tape major number to the kernel */ | ||
428 | rc = register_blkdev(tapeblock_major, "tBLK"); | ||
429 | if (rc < 0) | ||
430 | return rc; | ||
431 | |||
432 | if (tapeblock_major == 0) | ||
433 | tapeblock_major = rc; | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | /* | ||
438 | * Deregister major for block device frontend | ||
439 | */ | ||
440 | void | ||
441 | tapeblock_exit(void) | ||
442 | { | ||
443 | unregister_blkdev(tapeblock_major, "tBLK"); | ||
444 | } | ||
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 3c3f342149ec..e7650170274a 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c | |||
@@ -564,7 +564,6 @@ int | |||
564 | tape_std_mtreten(struct tape_device *device, int mt_count) | 564 | tape_std_mtreten(struct tape_device *device, int mt_count) |
565 | { | 565 | { |
566 | struct tape_request *request; | 566 | struct tape_request *request; |
567 | int rc; | ||
568 | 567 | ||
569 | request = tape_alloc_request(4, 0); | 568 | request = tape_alloc_request(4, 0); |
570 | if (IS_ERR(request)) | 569 | if (IS_ERR(request)) |
@@ -576,7 +575,7 @@ tape_std_mtreten(struct tape_device *device, int mt_count) | |||
576 | tape_ccw_cc(request->cpaddr + 2, NOP, 0, NULL); | 575 | tape_ccw_cc(request->cpaddr + 2, NOP, 0, NULL); |
577 | tape_ccw_end(request->cpaddr + 3, CCW_CMD_TIC, 0, request->cpaddr); | 576 | tape_ccw_end(request->cpaddr + 3, CCW_CMD_TIC, 0, request->cpaddr); |
578 | /* execute it, MTRETEN rc gets ignored */ | 577 | /* execute it, MTRETEN rc gets ignored */ |
579 | rc = tape_do_io_interruptible(device, request); | 578 | tape_do_io_interruptible(device, request); |
580 | tape_free_request(request); | 579 | tape_free_request(request); |
581 | return tape_mtop(device, MTREW, 1); | 580 | return tape_mtop(device, MTREW, 1); |
582 | } | 581 | } |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 0689fcf23a11..75c3f1f8fd43 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -326,6 +326,36 @@ static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area) | |||
326 | s390_process_res_acc(&link); | 326 | s390_process_res_acc(&link); |
327 | } | 327 | } |
328 | 328 | ||
329 | static void chsc_process_sei_chp_avail(struct chsc_sei_area *sei_area) | ||
330 | { | ||
331 | struct channel_path *chp; | ||
332 | struct chp_id chpid; | ||
333 | u8 *data; | ||
334 | int num; | ||
335 | |||
336 | CIO_CRW_EVENT(4, "chsc: channel path availability information\n"); | ||
337 | if (sei_area->rs != 0) | ||
338 | return; | ||
339 | data = sei_area->ccdf; | ||
340 | chp_id_init(&chpid); | ||
341 | for (num = 0; num <= __MAX_CHPID; num++) { | ||
342 | if (!chp_test_bit(data, num)) | ||
343 | continue; | ||
344 | chpid.id = num; | ||
345 | |||
346 | CIO_CRW_EVENT(4, "Update information for channel path " | ||
347 | "%x.%02x\n", chpid.cssid, chpid.id); | ||
348 | chp = chpid_to_chp(chpid); | ||
349 | if (!chp) { | ||
350 | chp_new(chpid); | ||
351 | continue; | ||
352 | } | ||
353 | mutex_lock(&chp->lock); | ||
354 | chsc_determine_base_channel_path_desc(chpid, &chp->desc); | ||
355 | mutex_unlock(&chp->lock); | ||
356 | } | ||
357 | } | ||
358 | |||
329 | struct chp_config_data { | 359 | struct chp_config_data { |
330 | u8 map[32]; | 360 | u8 map[32]; |
331 | u8 op; | 361 | u8 op; |
@@ -376,9 +406,12 @@ static void chsc_process_sei(struct chsc_sei_area *sei_area) | |||
376 | case 1: /* link incident*/ | 406 | case 1: /* link incident*/ |
377 | chsc_process_sei_link_incident(sei_area); | 407 | chsc_process_sei_link_incident(sei_area); |
378 | break; | 408 | break; |
379 | case 2: /* i/o resource accessibiliy */ | 409 | case 2: /* i/o resource accessibility */ |
380 | chsc_process_sei_res_acc(sei_area); | 410 | chsc_process_sei_res_acc(sei_area); |
381 | break; | 411 | break; |
412 | case 7: /* channel-path-availability information */ | ||
413 | chsc_process_sei_chp_avail(sei_area); | ||
414 | break; | ||
382 | case 8: /* channel-path-configuration notification */ | 415 | case 8: /* channel-path-configuration notification */ |
383 | chsc_process_sei_chp_config(sei_area); | 416 | chsc_process_sei_chp_config(sei_area); |
384 | break; | 417 | break; |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 6084103672b5..52c233fa2b12 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -408,9 +408,10 @@ ccw_device_done(struct ccw_device *cdev, int state) | |||
408 | CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel " | 408 | CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel " |
409 | "%04x\n", cdev->private->dev_id.devno, | 409 | "%04x\n", cdev->private->dev_id.devno, |
410 | sch->schid.sch_no); | 410 | sch->schid.sch_no); |
411 | if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) | 411 | if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) { |
412 | cdev->private->state = DEV_STATE_NOT_OPER; | ||
412 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 413 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
413 | else | 414 | } else |
414 | ccw_device_set_disconnected(cdev); | 415 | ccw_device_set_disconnected(cdev); |
415 | cdev->private->flags.donotify = 0; | 416 | cdev->private->flags.donotify = 0; |
416 | break; | 417 | break; |
@@ -840,9 +841,6 @@ call_handler: | |||
840 | static void | 841 | static void |
841 | ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event) | 842 | ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event) |
842 | { | 843 | { |
843 | struct subchannel *sch; | ||
844 | |||
845 | sch = to_subchannel(cdev->dev.parent); | ||
846 | ccw_device_set_timeout(cdev, 0); | 844 | ccw_device_set_timeout(cdev, 0); |
847 | /* Start delayed path verification. */ | 845 | /* Start delayed path verification. */ |
848 | ccw_device_online_verify(cdev, 0); | 846 | ccw_device_online_verify(cdev, 0); |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 651976b54af8..f98698d5735e 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
@@ -418,12 +418,9 @@ int ccw_device_resume(struct ccw_device *cdev) | |||
418 | int | 418 | int |
419 | ccw_device_call_handler(struct ccw_device *cdev) | 419 | ccw_device_call_handler(struct ccw_device *cdev) |
420 | { | 420 | { |
421 | struct subchannel *sch; | ||
422 | unsigned int stctl; | 421 | unsigned int stctl; |
423 | int ending_status; | 422 | int ending_status; |
424 | 423 | ||
425 | sch = to_subchannel(cdev->dev.parent); | ||
426 | |||
427 | /* | 424 | /* |
428 | * we allow for the device action handler if . | 425 | * we allow for the device action handler if . |
429 | * - we received ending status | 426 | * - we received ending status |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index e8f267eb8887..55e8f721e38a 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -1446,7 +1446,7 @@ set: | |||
1446 | static int handle_outbound(struct qdio_q *q, unsigned int callflags, | 1446 | static int handle_outbound(struct qdio_q *q, unsigned int callflags, |
1447 | int bufnr, int count) | 1447 | int bufnr, int count) |
1448 | { | 1448 | { |
1449 | unsigned char state; | 1449 | unsigned char state = 0; |
1450 | int used, rc = 0; | 1450 | int used, rc = 0; |
1451 | 1451 | ||
1452 | qperf_inc(q, outbound_call); | 1452 | qperf_inc(q, outbound_call); |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 67302b944ab3..16e4a25596e7 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -1183,8 +1183,12 @@ static void ap_scan_bus(struct work_struct *unused) | |||
1183 | INIT_LIST_HEAD(&ap_dev->list); | 1183 | INIT_LIST_HEAD(&ap_dev->list); |
1184 | setup_timer(&ap_dev->timeout, ap_request_timeout, | 1184 | setup_timer(&ap_dev->timeout, ap_request_timeout, |
1185 | (unsigned long) ap_dev); | 1185 | (unsigned long) ap_dev); |
1186 | if (device_type == 0) | 1186 | if (device_type == 0) { |
1187 | ap_probe_device_type(ap_dev); | 1187 | if (ap_probe_device_type(ap_dev)) { |
1188 | kfree(ap_dev); | ||
1189 | continue; | ||
1190 | } | ||
1191 | } | ||
1188 | else | 1192 | else |
1189 | ap_dev->device_type = device_type; | 1193 | ap_dev->device_type = device_type; |
1190 | 1194 | ||