aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/Makefile4
-rw-r--r--drivers/s390/char/con3215.c2
-rw-r--r--drivers/s390/char/con3270.c3
-rw-r--r--drivers/s390/char/defkeymap.c2
-rw-r--r--drivers/s390/char/fs3270.c4
-rw-r--r--drivers/s390/char/keyboard.c2
-rw-r--r--drivers/s390/char/monreader.c218
-rw-r--r--drivers/s390/char/monwriter.c4
-rw-r--r--drivers/s390/char/raw3270.c4
-rw-r--r--drivers/s390/char/sclp.c93
-rw-r--r--drivers/s390/char/sclp.h18
-rw-r--r--drivers/s390/char/sclp_con.c2
-rw-r--r--drivers/s390/char/sclp_cpi.c2
-rw-r--r--drivers/s390/char/sclp_info.c57
-rw-r--r--drivers/s390/char/sclp_rw.c2
-rw-r--r--drivers/s390/char/sclp_tty.c2
-rw-r--r--drivers/s390/char/sclp_vt220.c4
-rw-r--r--drivers/s390/char/tape.h22
-rw-r--r--drivers/s390/char/tape_3590.c479
-rw-r--r--drivers/s390/char/tape_3590.h53
-rw-r--r--drivers/s390/char/tape_block.c4
-rw-r--r--drivers/s390/char/tape_char.c27
-rw-r--r--drivers/s390/char/tape_core.c69
-rw-r--r--drivers/s390/char/tty3270.c13
-rw-r--r--drivers/s390/char/vmlogrdr.c284
25 files changed, 973 insertions, 401 deletions
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index c3e97b4fc186..293e667b50f2 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -2,7 +2,8 @@
2# S/390 character devices 2# S/390 character devices
3# 3#
4 4
5obj-y += ctrlchar.o keyboard.o defkeymap.o 5obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
6 sclp_info.o
6 7
7obj-$(CONFIG_TN3270) += raw3270.o 8obj-$(CONFIG_TN3270) += raw3270.o
8obj-$(CONFIG_TN3270_CONSOLE) += con3270.o 9obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
@@ -11,7 +12,6 @@ obj-$(CONFIG_TN3270_FS) += fs3270.o
11 12
12obj-$(CONFIG_TN3215) += con3215.o 13obj-$(CONFIG_TN3215) += con3215.o
13 14
14obj-$(CONFIG_SCLP) += sclp.o sclp_rw.o sclp_quiesce.o
15obj-$(CONFIG_SCLP_TTY) += sclp_tty.o 15obj-$(CONFIG_SCLP_TTY) += sclp_tty.o
16obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o 16obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o
17obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o 17obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 25b5d7a66417..9a328f14a641 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -1121,7 +1121,7 @@ static const struct tty_operations tty3215_ops = {
1121 * 3215 tty registration code called from tty_init(). 1121 * 3215 tty registration code called from tty_init().
1122 * Most kernel services (incl. kmalloc) are available at this poimt. 1122 * Most kernel services (incl. kmalloc) are available at this poimt.
1123 */ 1123 */
1124int __init 1124static int __init
1125tty3215_init(void) 1125tty3215_init(void)
1126{ 1126{
1127 struct tty_driver *driver; 1127 struct tty_driver *driver;
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 7566be890688..8e7f2d7633d6 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -69,8 +69,7 @@ static void con3270_update(struct con3270 *);
69/* 69/*
70 * Setup timeout for a device. On timeout trigger an update. 70 * Setup timeout for a device. On timeout trigger an update.
71 */ 71 */
72void 72static void con3270_set_timer(struct con3270 *cp, int expires)
73con3270_set_timer(struct con3270 *cp, int expires)
74{ 73{
75 if (expires == 0) { 74 if (expires == 0) {
76 if (timer_pending(&cp->timer)) 75 if (timer_pending(&cp->timer))
diff --git a/drivers/s390/char/defkeymap.c b/drivers/s390/char/defkeymap.c
index 17027d918cf7..564baca01b7c 100644
--- a/drivers/s390/char/defkeymap.c
+++ b/drivers/s390/char/defkeymap.c
@@ -5,6 +5,8 @@
5#include <linux/types.h> 5#include <linux/types.h>
6#include <linux/keyboard.h> 6#include <linux/keyboard.h>
7#include <linux/kd.h> 7#include <linux/kd.h>
8#include <linux/kbd_kern.h>
9#include <linux/kbd_diacr.h>
8 10
9u_short plain_map[NR_KEYS] = { 11u_short plain_map[NR_KEYS] = {
10 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 12 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000,
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 0893d306ae80..e1a746269c4c 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -23,7 +23,7 @@
23#include "raw3270.h" 23#include "raw3270.h"
24#include "ctrlchar.h" 24#include "ctrlchar.h"
25 25
26struct raw3270_fn fs3270_fn; 26static struct raw3270_fn fs3270_fn;
27 27
28struct fs3270 { 28struct fs3270 {
29 struct raw3270_view view; 29 struct raw3270_view view;
@@ -401,7 +401,7 @@ fs3270_release(struct raw3270_view *view)
401} 401}
402 402
403/* View to a 3270 device. Can be console, tty or fullscreen. */ 403/* View to a 3270 device. Can be console, tty or fullscreen. */
404struct raw3270_fn fs3270_fn = { 404static struct raw3270_fn fs3270_fn = {
405 .activate = fs3270_activate, 405 .activate = fs3270_activate,
406 .deactivate = fs3270_deactivate, 406 .deactivate = fs3270_deactivate,
407 .intv = (void *) fs3270_irq, 407 .intv = (void *) fs3270_irq,
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 3e86fd1756e5..f62f9a4e8950 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -148,6 +148,7 @@ kbd_ascebc(struct kbd_data *kbd, unsigned char *ascebc)
148 } 148 }
149} 149}
150 150
151#if 0
151/* 152/*
152 * Generate ebcdic -> ascii translation table from kbd_data. 153 * Generate ebcdic -> ascii translation table from kbd_data.
153 */ 154 */
@@ -173,6 +174,7 @@ kbd_ebcasc(struct kbd_data *kbd, unsigned char *ebcasc)
173 } 174 }
174 } 175 }
175} 176}
177#endif
176 178
177/* 179/*
178 * We have a combining character DIACR here, followed by the character CH. 180 * We have a combining character DIACR here, followed by the character CH.
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index a138b1510093..3a1a958fb5f2 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Character device driver for reading z/VM *MONITOR service records. 4 * Character device driver for reading z/VM *MONITOR service records.
5 * 5 *
6 * Copyright (C) 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH. 6 * Copyright 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
7 * 7 *
8 * Author: Gerald Schaefer <geraldsc@de.ibm.com> 8 * Author: Gerald Schaefer <geraldsc@de.ibm.com>
9 */ 9 */
@@ -22,7 +22,7 @@
22#include <asm/ebcdic.h> 22#include <asm/ebcdic.h>
23#include <asm/extmem.h> 23#include <asm/extmem.h>
24#include <linux/poll.h> 24#include <linux/poll.h>
25#include "../net/iucv.h" 25#include <net/iucv/iucv.h>
26 26
27 27
28//#define MON_DEBUG /* Debug messages on/off */ 28//#define MON_DEBUG /* Debug messages on/off */
@@ -50,14 +50,13 @@ static char mon_dcss_name[9] = "MONDCSS\0";
50struct mon_msg { 50struct mon_msg {
51 u32 pos; 51 u32 pos;
52 u32 mca_offset; 52 u32 mca_offset;
53 iucv_MessagePending local_eib; 53 struct iucv_message msg;
54 char msglim_reached; 54 char msglim_reached;
55 char replied_msglim; 55 char replied_msglim;
56}; 56};
57 57
58struct mon_private { 58struct mon_private {
59 u16 pathid; 59 struct iucv_path *path;
60 iucv_handle_t iucv_handle;
61 struct mon_msg *msg_array[MON_MSGLIM]; 60 struct mon_msg *msg_array[MON_MSGLIM];
62 unsigned int write_index; 61 unsigned int write_index;
63 unsigned int read_index; 62 unsigned int read_index;
@@ -75,8 +74,6 @@ static unsigned long mon_dcss_end;
75static DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue); 74static DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue);
76static DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue); 75static DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue);
77 76
78static u8 iucv_host[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
79
80static u8 user_data_connect[16] = { 77static u8 user_data_connect[16] = {
81 /* Version code, must be 0x01 for shared mode */ 78 /* Version code, must be 0x01 for shared mode */
82 0x01, 79 0x01,
@@ -100,8 +97,7 @@ static u8 user_data_sever[16] = {
100 * Create the 8 bytes EBCDIC DCSS segment name from 97 * Create the 8 bytes EBCDIC DCSS segment name from
101 * an ASCII name, incl. padding 98 * an ASCII name, incl. padding
102 */ 99 */
103static inline void 100static inline void dcss_mkname(char *ascii_name, char *ebcdic_name)
104dcss_mkname(char *ascii_name, char *ebcdic_name)
105{ 101{
106 int i; 102 int i;
107 103
@@ -119,8 +115,7 @@ dcss_mkname(char *ascii_name, char *ebcdic_name)
119 * print appropriate error message for segment_load()/segment_type() 115 * print appropriate error message for segment_load()/segment_type()
120 * return code 116 * return code
121 */ 117 */
122static void 118static void mon_segment_warn(int rc, char* seg_name)
123mon_segment_warn(int rc, char* seg_name)
124{ 119{
125 switch (rc) { 120 switch (rc) {
126 case -ENOENT: 121 case -ENOENT:
@@ -166,44 +161,37 @@ mon_segment_warn(int rc, char* seg_name)
166 } 161 }
167} 162}
168 163
169static inline unsigned long 164static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
170mon_mca_start(struct mon_msg *monmsg)
171{ 165{
172 return monmsg->local_eib.ln1msg1.iprmmsg1_u32; 166 return *(u32 *) &monmsg->msg.rmmsg;
173} 167}
174 168
175static inline unsigned long 169static inline unsigned long mon_mca_end(struct mon_msg *monmsg)
176mon_mca_end(struct mon_msg *monmsg)
177{ 170{
178 return monmsg->local_eib.ln1msg2.ipbfln1f; 171 return *(u32 *) &monmsg->msg.rmmsg[4];
179} 172}
180 173
181static inline u8 174static inline u8 mon_mca_type(struct mon_msg *monmsg, u8 index)
182mon_mca_type(struct mon_msg *monmsg, u8 index)
183{ 175{
184 return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index); 176 return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index);
185} 177}
186 178
187static inline u32 179static inline u32 mon_mca_size(struct mon_msg *monmsg)
188mon_mca_size(struct mon_msg *monmsg)
189{ 180{
190 return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1; 181 return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1;
191} 182}
192 183
193static inline u32 184static inline u32 mon_rec_start(struct mon_msg *monmsg)
194mon_rec_start(struct mon_msg *monmsg)
195{ 185{
196 return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4)); 186 return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4));
197} 187}
198 188
199static inline u32 189static inline u32 mon_rec_end(struct mon_msg *monmsg)
200mon_rec_end(struct mon_msg *monmsg)
201{ 190{
202 return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8)); 191 return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8));
203} 192}
204 193
205static inline int 194static inline int mon_check_mca(struct mon_msg *monmsg)
206mon_check_mca(struct mon_msg *monmsg)
207{ 195{
208 if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) || 196 if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
209 (mon_rec_start(monmsg) < mon_dcss_start) || 197 (mon_rec_start(monmsg) < mon_dcss_start) ||
@@ -221,20 +209,17 @@ mon_check_mca(struct mon_msg *monmsg)
221 return 0; 209 return 0;
222} 210}
223 211
224static inline int 212static inline int mon_send_reply(struct mon_msg *monmsg,
225mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv) 213 struct mon_private *monpriv)
226{ 214{
227 u8 prmmsg[8];
228 int rc; 215 int rc;
229 216
230 P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = " 217 P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
231 "0x%08X\n\n", 218 "0x%08X\n\n",
232 monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid, 219 monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
233 monmsg->local_eib.iptrgcls); 220
234 rc = iucv_reply_prmmsg(monmsg->local_eib.ippathid, 221 rc = iucv_message_reply(monpriv->path, &monmsg->msg,
235 monmsg->local_eib.ipmsgid, 222 IUCV_IPRMDATA, NULL, 0);
236 monmsg->local_eib.iptrgcls,
237 0, prmmsg);
238 atomic_dec(&monpriv->msglim_count); 223 atomic_dec(&monpriv->msglim_count);
239 if (likely(!monmsg->msglim_reached)) { 224 if (likely(!monmsg->msglim_reached)) {
240 monmsg->pos = 0; 225 monmsg->pos = 0;
@@ -251,10 +236,19 @@ mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv)
251 return 0; 236 return 0;
252} 237}
253 238
254static inline struct mon_private * 239static inline void mon_free_mem(struct mon_private *monpriv)
255mon_alloc_mem(void) 240{
241 int i;
242
243 for (i = 0; i < MON_MSGLIM; i++)
244 if (monpriv->msg_array[i])
245 kfree(monpriv->msg_array[i]);
246 kfree(monpriv);
247}
248
249static inline struct mon_private *mon_alloc_mem(void)
256{ 250{
257 int i,j; 251 int i;
258 struct mon_private *monpriv; 252 struct mon_private *monpriv;
259 253
260 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); 254 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
@@ -267,16 +261,15 @@ mon_alloc_mem(void)
267 GFP_KERNEL); 261 GFP_KERNEL);
268 if (!monpriv->msg_array[i]) { 262 if (!monpriv->msg_array[i]) {
269 P_ERROR("open, no memory for msg_array\n"); 263 P_ERROR("open, no memory for msg_array\n");
270 for (j = 0; j < i; j++) 264 mon_free_mem(monpriv);
271 kfree(monpriv->msg_array[j]);
272 return NULL; 265 return NULL;
273 } 266 }
274 } 267 }
275 return monpriv; 268 return monpriv;
276} 269}
277 270
278static inline void 271static inline void mon_read_debug(struct mon_msg *monmsg,
279mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv) 272 struct mon_private *monpriv)
280{ 273{
281#ifdef MON_DEBUG 274#ifdef MON_DEBUG
282 u8 msg_type[2], mca_type; 275 u8 msg_type[2], mca_type;
@@ -284,7 +277,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
284 277
285 records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1; 278 records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;
286 279
287 memcpy(msg_type, &monmsg->local_eib.iptrgcls, 2); 280 memcpy(msg_type, &monmsg->msg.class, 2);
288 EBCASC(msg_type, 2); 281 EBCASC(msg_type, 2);
289 mca_type = mon_mca_type(monmsg, 0); 282 mca_type = mon_mca_type(monmsg, 0);
290 EBCASC(&mca_type, 1); 283 EBCASC(&mca_type, 1);
@@ -292,8 +285,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
292 P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n", 285 P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
293 monpriv->read_index, monpriv->write_index); 286 monpriv->read_index, monpriv->write_index);
294 P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n", 287 P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
295 monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid, 288 monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
296 monmsg->local_eib.iptrgcls);
297 P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n", 289 P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",
298 msg_type[0], msg_type[1], mca_type ? mca_type : 'X', 290 msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
299 mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2)); 291 mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
@@ -306,8 +298,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
306#endif 298#endif
307} 299}
308 300
309static inline void 301static inline void mon_next_mca(struct mon_msg *monmsg)
310mon_next_mca(struct mon_msg *monmsg)
311{ 302{
312 if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12)) 303 if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
313 return; 304 return;
@@ -316,8 +307,7 @@ mon_next_mca(struct mon_msg *monmsg)
316 monmsg->pos = 0; 307 monmsg->pos = 0;
317} 308}
318 309
319static inline struct mon_msg * 310static inline struct mon_msg *mon_next_message(struct mon_private *monpriv)
320mon_next_message(struct mon_private *monpriv)
321{ 311{
322 struct mon_msg *monmsg; 312 struct mon_msg *monmsg;
323 313
@@ -342,39 +332,37 @@ mon_next_message(struct mon_private *monpriv)
342/****************************************************************************** 332/******************************************************************************
343 * IUCV handler * 333 * IUCV handler *
344 *****************************************************************************/ 334 *****************************************************************************/
345static void 335static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
346mon_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data)
347{ 336{
348 struct mon_private *monpriv = (struct mon_private *) pgm_data; 337 struct mon_private *monpriv = path->private;
349 338
350 P_DEBUG("IUCV connection completed\n"); 339 P_DEBUG("IUCV connection completed\n");
351 P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = " 340 P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
352 "0x%02X, Sample = 0x%02X\n", 341 "0x%02X, Sample = 0x%02X\n",
353 eib->ipuser[0], eib->ipuser[1], eib->ipuser[2]); 342 ipuser[0], ipuser[1], ipuser[2]);
354 atomic_set(&monpriv->iucv_connected, 1); 343 atomic_set(&monpriv->iucv_connected, 1);
355 wake_up(&mon_conn_wait_queue); 344 wake_up(&mon_conn_wait_queue);
356} 345}
357 346
358static void 347static void mon_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
359mon_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data)
360{ 348{
361 struct mon_private *monpriv = (struct mon_private *) pgm_data; 349 struct mon_private *monpriv = path->private;
362 350
363 P_ERROR("IUCV connection severed with rc = 0x%X\n", 351 P_ERROR("IUCV connection severed with rc = 0x%X\n", ipuser[0]);
364 (u8) eib->ipuser[0]); 352 iucv_path_sever(path, NULL);
365 atomic_set(&monpriv->iucv_severed, 1); 353 atomic_set(&monpriv->iucv_severed, 1);
366 wake_up(&mon_conn_wait_queue); 354 wake_up(&mon_conn_wait_queue);
367 wake_up_interruptible(&mon_read_wait_queue); 355 wake_up_interruptible(&mon_read_wait_queue);
368} 356}
369 357
370static void 358static void mon_iucv_message_pending(struct iucv_path *path,
371mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data) 359 struct iucv_message *msg)
372{ 360{
373 struct mon_private *monpriv = (struct mon_private *) pgm_data; 361 struct mon_private *monpriv = path->private;
374 362
375 P_DEBUG("IUCV message pending\n"); 363 P_DEBUG("IUCV message pending\n");
376 memcpy(&monpriv->msg_array[monpriv->write_index]->local_eib, eib, 364 memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
377 sizeof(iucv_MessagePending)); 365 msg, sizeof(*msg));
378 if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) { 366 if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
379 P_WARNING("IUCV message pending, message limit (%i) reached\n", 367 P_WARNING("IUCV message pending, message limit (%i) reached\n",
380 MON_MSGLIM); 368 MON_MSGLIM);
@@ -385,54 +373,45 @@ mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data)
385 wake_up_interruptible(&mon_read_wait_queue); 373 wake_up_interruptible(&mon_read_wait_queue);
386} 374}
387 375
388static iucv_interrupt_ops_t mon_iucvops = { 376static struct iucv_handler monreader_iucv_handler = {
389 .ConnectionComplete = mon_iucv_ConnectionComplete, 377 .path_complete = mon_iucv_path_complete,
390 .ConnectionSevered = mon_iucv_ConnectionSevered, 378 .path_severed = mon_iucv_path_severed,
391 .MessagePending = mon_iucv_MessagePending, 379 .message_pending = mon_iucv_message_pending,
392}; 380};
393 381
394/****************************************************************************** 382/******************************************************************************
395 * file operations * 383 * file operations *
396 *****************************************************************************/ 384 *****************************************************************************/
397static int 385static int mon_open(struct inode *inode, struct file *filp)
398mon_open(struct inode *inode, struct file *filp)
399{ 386{
400 int rc, i;
401 struct mon_private *monpriv; 387 struct mon_private *monpriv;
388 int rc;
402 389
403 /* 390 /*
404 * only one user allowed 391 * only one user allowed
405 */ 392 */
393 rc = -EBUSY;
406 if (test_and_set_bit(MON_IN_USE, &mon_in_use)) 394 if (test_and_set_bit(MON_IN_USE, &mon_in_use))
407 return -EBUSY; 395 goto out;
408 396
397 rc = -ENOMEM;
409 monpriv = mon_alloc_mem(); 398 monpriv = mon_alloc_mem();
410 if (!monpriv) 399 if (!monpriv)
411 return -ENOMEM; 400 goto out_use;
412 401
413 /* 402 /*
414 * Register with IUCV and connect to *MONITOR service 403 * Connect to *MONITOR service
415 */ 404 */
416 monpriv->iucv_handle = iucv_register_program("my_monreader ", 405 monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL);
417 MON_SERVICE, 406 if (!monpriv->path)
418 NULL, 407 goto out_priv;
419 &mon_iucvops, 408 rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler,
420 monpriv); 409 MON_SERVICE, NULL, user_data_connect, monpriv);
421 if (!monpriv->iucv_handle) {
422 P_ERROR("failed to register with iucv driver\n");
423 rc = -EIO;
424 goto out_error;
425 }
426 P_INFO("open, registered with IUCV\n");
427
428 rc = iucv_connect(&monpriv->pathid, MON_MSGLIM, user_data_connect,
429 MON_SERVICE, iucv_host, IPRMDATA, NULL, NULL,
430 monpriv->iucv_handle, NULL);
431 if (rc) { 410 if (rc) {
432 P_ERROR("iucv connection to *MONITOR failed with " 411 P_ERROR("iucv connection to *MONITOR failed with "
433 "IPUSER SEVER code = %i\n", rc); 412 "IPUSER SEVER code = %i\n", rc);
434 rc = -EIO; 413 rc = -EIO;
435 goto out_unregister; 414 goto out_path;
436 } 415 }
437 /* 416 /*
438 * Wait for connection confirmation 417 * Wait for connection confirmation
@@ -444,24 +423,23 @@ mon_open(struct inode *inode, struct file *filp)
444 atomic_set(&monpriv->iucv_severed, 0); 423 atomic_set(&monpriv->iucv_severed, 0);
445 atomic_set(&monpriv->iucv_connected, 0); 424 atomic_set(&monpriv->iucv_connected, 0);
446 rc = -EIO; 425 rc = -EIO;
447 goto out_unregister; 426 goto out_path;
448 } 427 }
449 P_INFO("open, established connection to *MONITOR service\n\n"); 428 P_INFO("open, established connection to *MONITOR service\n\n");
450 filp->private_data = monpriv; 429 filp->private_data = monpriv;
451 return nonseekable_open(inode, filp); 430 return nonseekable_open(inode, filp);
452 431
453out_unregister: 432out_path:
454 iucv_unregister_program(monpriv->iucv_handle); 433 kfree(monpriv->path);
455out_error: 434out_priv:
456 for (i = 0; i < MON_MSGLIM; i++) 435 mon_free_mem(monpriv);
457 kfree(monpriv->msg_array[i]); 436out_use:
458 kfree(monpriv);
459 clear_bit(MON_IN_USE, &mon_in_use); 437 clear_bit(MON_IN_USE, &mon_in_use);
438out:
460 return rc; 439 return rc;
461} 440}
462 441
463static int 442static int mon_close(struct inode *inode, struct file *filp)
464mon_close(struct inode *inode, struct file *filp)
465{ 443{
466 int rc, i; 444 int rc, i;
467 struct mon_private *monpriv = filp->private_data; 445 struct mon_private *monpriv = filp->private_data;
@@ -469,18 +447,12 @@ mon_close(struct inode *inode, struct file *filp)
469 /* 447 /*
470 * Close IUCV connection and unregister 448 * Close IUCV connection and unregister
471 */ 449 */
472 rc = iucv_sever(monpriv->pathid, user_data_sever); 450 rc = iucv_path_sever(monpriv->path, user_data_sever);
473 if (rc) 451 if (rc)
474 P_ERROR("close, iucv_sever failed with rc = %i\n", rc); 452 P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
475 else 453 else
476 P_INFO("close, terminated connection to *MONITOR service\n"); 454 P_INFO("close, terminated connection to *MONITOR service\n");
477 455
478 rc = iucv_unregister_program(monpriv->iucv_handle);
479 if (rc)
480 P_ERROR("close, iucv_unregister failed with rc = %i\n", rc);
481 else
482 P_INFO("close, unregistered with IUCV\n");
483
484 atomic_set(&monpriv->iucv_severed, 0); 456 atomic_set(&monpriv->iucv_severed, 0);
485 atomic_set(&monpriv->iucv_connected, 0); 457 atomic_set(&monpriv->iucv_connected, 0);
486 atomic_set(&monpriv->read_ready, 0); 458 atomic_set(&monpriv->read_ready, 0);
@@ -495,8 +467,8 @@ mon_close(struct inode *inode, struct file *filp)
495 return 0; 467 return 0;
496} 468}
497 469
498static ssize_t 470static ssize_t mon_read(struct file *filp, char __user *data,
499mon_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) 471 size_t count, loff_t *ppos)
500{ 472{
501 struct mon_private *monpriv = filp->private_data; 473 struct mon_private *monpriv = filp->private_data;
502 struct mon_msg *monmsg; 474 struct mon_msg *monmsg;
@@ -563,8 +535,7 @@ out_copy:
563 return count; 535 return count;
564} 536}
565 537
566static unsigned int 538static unsigned int mon_poll(struct file *filp, struct poll_table_struct *p)
567mon_poll(struct file *filp, struct poll_table_struct *p)
568{ 539{
569 struct mon_private *monpriv = filp->private_data; 540 struct mon_private *monpriv = filp->private_data;
570 541
@@ -593,8 +564,7 @@ static struct miscdevice mon_dev = {
593/****************************************************************************** 564/******************************************************************************
594 * module init/exit * 565 * module init/exit *
595 *****************************************************************************/ 566 *****************************************************************************/
596static int __init 567static int __init mon_init(void)
597mon_init(void)
598{ 568{
599 int rc; 569 int rc;
600 570
@@ -603,22 +573,34 @@ mon_init(void)
603 return -ENODEV; 573 return -ENODEV;
604 } 574 }
605 575
576 /*
577 * Register with IUCV and connect to *MONITOR service
578 */
579 rc = iucv_register(&monreader_iucv_handler, 1);
580 if (rc) {
581 P_ERROR("failed to register with iucv driver\n");
582 return rc;
583 }
584 P_INFO("open, registered with IUCV\n");
585
606 rc = segment_type(mon_dcss_name); 586 rc = segment_type(mon_dcss_name);
607 if (rc < 0) { 587 if (rc < 0) {
608 mon_segment_warn(rc, mon_dcss_name); 588 mon_segment_warn(rc, mon_dcss_name);
609 return rc; 589 goto out_iucv;
610 } 590 }
611 if (rc != SEG_TYPE_SC) { 591 if (rc != SEG_TYPE_SC) {
612 P_ERROR("segment %s has unsupported type, should be SC\n", 592 P_ERROR("segment %s has unsupported type, should be SC\n",
613 mon_dcss_name); 593 mon_dcss_name);
614 return -EINVAL; 594 rc = -EINVAL;
595 goto out_iucv;
615 } 596 }
616 597
617 rc = segment_load(mon_dcss_name, SEGMENT_SHARED, 598 rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
618 &mon_dcss_start, &mon_dcss_end); 599 &mon_dcss_start, &mon_dcss_end);
619 if (rc < 0) { 600 if (rc < 0) {
620 mon_segment_warn(rc, mon_dcss_name); 601 mon_segment_warn(rc, mon_dcss_name);
621 return -EINVAL; 602 rc = -EINVAL;
603 goto out_iucv;
622 } 604 }
623 dcss_mkname(mon_dcss_name, &user_data_connect[8]); 605 dcss_mkname(mon_dcss_name, &user_data_connect[8]);
624 606
@@ -634,14 +616,16 @@ mon_init(void)
634 616
635out: 617out:
636 segment_unload(mon_dcss_name); 618 segment_unload(mon_dcss_name);
619out_iucv:
620 iucv_unregister(&monreader_iucv_handler, 1);
637 return rc; 621 return rc;
638} 622}
639 623
640static void __exit 624static void __exit mon_exit(void)
641mon_exit(void)
642{ 625{
643 segment_unload(mon_dcss_name); 626 segment_unload(mon_dcss_name);
644 WARN_ON(misc_deregister(&mon_dev) != 0); 627 WARN_ON(misc_deregister(&mon_dev) != 0);
628 iucv_unregister(&monreader_iucv_handler, 1);
645 return; 629 return;
646} 630}
647 631
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index cdb24f528112..9e451acc6491 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -67,8 +67,8 @@ static int monwrite_diag(struct monwrite_hdr *myhdr, char *buffer, int fcn)
67 return -EINVAL; 67 return -EINVAL;
68} 68}
69 69
70static inline struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv, 70static struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv,
71 struct monwrite_hdr *monhdr) 71 struct monwrite_hdr *monhdr)
72{ 72{
73 struct mon_buf *entry, *next; 73 struct mon_buf *entry, *next;
74 74
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 7a84014f2037..8facd14adb7c 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -29,7 +29,7 @@
29#include <linux/device.h> 29#include <linux/device.h>
30#include <linux/mutex.h> 30#include <linux/mutex.h>
31 31
32struct class *class3270; 32static struct class *class3270;
33 33
34/* The main 3270 data structure. */ 34/* The main 3270 data structure. */
35struct raw3270 { 35struct raw3270 {
@@ -86,7 +86,7 @@ DECLARE_WAIT_QUEUE_HEAD(raw3270_wait_queue);
86/* 86/*
87 * Encode array for 12 bit 3270 addresses. 87 * Encode array for 12 bit 3270 addresses.
88 */ 88 */
89unsigned char raw3270_ebcgraf[64] = { 89static unsigned char raw3270_ebcgraf[64] = {
90 0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 90 0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
91 0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 91 0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
92 0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 92 0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 8a056df09d6b..f171de3b0b11 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -59,7 +59,8 @@ static volatile enum sclp_init_state_t {
59/* Internal state: is a request active at the sclp? */ 59/* Internal state: is a request active at the sclp? */
60static volatile enum sclp_running_state_t { 60static volatile enum sclp_running_state_t {
61 sclp_running_state_idle, 61 sclp_running_state_idle,
62 sclp_running_state_running 62 sclp_running_state_running,
63 sclp_running_state_reset_pending
63} sclp_running_state = sclp_running_state_idle; 64} sclp_running_state = sclp_running_state_idle;
64 65
65/* Internal state: is a read request pending? */ 66/* Internal state: is a read request pending? */
@@ -88,15 +89,15 @@ static volatile enum sclp_mask_state_t {
88 89
89/* Timeout intervals in seconds.*/ 90/* Timeout intervals in seconds.*/
90#define SCLP_BUSY_INTERVAL 10 91#define SCLP_BUSY_INTERVAL 10
91#define SCLP_RETRY_INTERVAL 15 92#define SCLP_RETRY_INTERVAL 30
92 93
93static void sclp_process_queue(void); 94static void sclp_process_queue(void);
94static int sclp_init_mask(int calculate); 95static int sclp_init_mask(int calculate);
95static int sclp_init(void); 96static int sclp_init(void);
96 97
97/* Perform service call. Return 0 on success, non-zero otherwise. */ 98/* Perform service call. Return 0 on success, non-zero otherwise. */
98static int 99int
99service_call(sclp_cmdw_t command, void *sccb) 100sclp_service_call(sclp_cmdw_t command, void *sccb)
100{ 101{
101 int cc; 102 int cc;
102 103
@@ -113,19 +114,17 @@ service_call(sclp_cmdw_t command, void *sccb)
113 return 0; 114 return 0;
114} 115}
115 116
116/* Request timeout handler. Restart the request queue. If DATA is non-zero, 117static inline void __sclp_make_read_req(void);
117 * force restart of running request. */ 118
118static void 119static void
119sclp_request_timeout(unsigned long data) 120__sclp_queue_read_req(void)
120{ 121{
121 unsigned long flags; 122 if (sclp_reading_state == sclp_reading_state_idle) {
122 123 sclp_reading_state = sclp_reading_state_reading;
123 if (data) { 124 __sclp_make_read_req();
124 spin_lock_irqsave(&sclp_lock, flags); 125 /* Add request to head of queue */
125 sclp_running_state = sclp_running_state_idle; 126 list_add(&sclp_read_req.list, &sclp_req_queue);
126 spin_unlock_irqrestore(&sclp_lock, flags);
127 } 127 }
128 sclp_process_queue();
129} 128}
130 129
131/* Set up request retry timer. Called while sclp_lock is locked. */ 130/* Set up request retry timer. Called while sclp_lock is locked. */
@@ -140,6 +139,29 @@ __sclp_set_request_timer(unsigned long time, void (*function)(unsigned long),
140 add_timer(&sclp_request_timer); 139 add_timer(&sclp_request_timer);
141} 140}
142 141
142/* Request timeout handler. Restart the request queue. If DATA is non-zero,
143 * force restart of running request. */
144static void
145sclp_request_timeout(unsigned long data)
146{
147 unsigned long flags;
148
149 spin_lock_irqsave(&sclp_lock, flags);
150 if (data) {
151 if (sclp_running_state == sclp_running_state_running) {
152 /* Break running state and queue NOP read event request
153 * to get a defined interface state. */
154 __sclp_queue_read_req();
155 sclp_running_state = sclp_running_state_idle;
156 }
157 } else {
158 __sclp_set_request_timer(SCLP_BUSY_INTERVAL * HZ,
159 sclp_request_timeout, 0);
160 }
161 spin_unlock_irqrestore(&sclp_lock, flags);
162 sclp_process_queue();
163}
164
143/* Try to start a request. Return zero if the request was successfully 165/* Try to start a request. Return zero if the request was successfully
144 * started or if it will be started at a later time. Return non-zero otherwise. 166 * started or if it will be started at a later time. Return non-zero otherwise.
145 * Called while sclp_lock is locked. */ 167 * Called while sclp_lock is locked. */
@@ -151,7 +173,7 @@ __sclp_start_request(struct sclp_req *req)
151 if (sclp_running_state != sclp_running_state_idle) 173 if (sclp_running_state != sclp_running_state_idle)
152 return 0; 174 return 0;
153 del_timer(&sclp_request_timer); 175 del_timer(&sclp_request_timer);
154 rc = service_call(req->command, req->sccb); 176 rc = sclp_service_call(req->command, req->sccb);
155 req->start_count++; 177 req->start_count++;
156 178
157 if (rc == 0) { 179 if (rc == 0) {
@@ -191,7 +213,15 @@ sclp_process_queue(void)
191 rc = __sclp_start_request(req); 213 rc = __sclp_start_request(req);
192 if (rc == 0) 214 if (rc == 0)
193 break; 215 break;
194 /* Request failed. */ 216 /* Request failed */
217 if (req->start_count > 1) {
218 /* Cannot abort already submitted request - could still
219 * be active at the SCLP */
220 __sclp_set_request_timer(SCLP_BUSY_INTERVAL * HZ,
221 sclp_request_timeout, 0);
222 break;
223 }
224 /* Post-processing for aborted request */
195 list_del(&req->list); 225 list_del(&req->list);
196 if (req->callback) { 226 if (req->callback) {
197 spin_unlock_irqrestore(&sclp_lock, flags); 227 spin_unlock_irqrestore(&sclp_lock, flags);
@@ -221,7 +251,8 @@ sclp_add_request(struct sclp_req *req)
221 list_add_tail(&req->list, &sclp_req_queue); 251 list_add_tail(&req->list, &sclp_req_queue);
222 rc = 0; 252 rc = 0;
223 /* Start if request is first in list */ 253 /* Start if request is first in list */
224 if (req->list.prev == &sclp_req_queue) { 254 if (sclp_running_state == sclp_running_state_idle &&
255 req->list.prev == &sclp_req_queue) {
225 rc = __sclp_start_request(req); 256 rc = __sclp_start_request(req);
226 if (rc) 257 if (rc)
227 list_del(&req->list); 258 list_del(&req->list);
@@ -294,7 +325,7 @@ __sclp_make_read_req(void)
294 sccb = (struct sccb_header *) sclp_read_sccb; 325 sccb = (struct sccb_header *) sclp_read_sccb;
295 clear_page(sccb); 326 clear_page(sccb);
296 memset(&sclp_read_req, 0, sizeof(struct sclp_req)); 327 memset(&sclp_read_req, 0, sizeof(struct sclp_req));
297 sclp_read_req.command = SCLP_CMDW_READDATA; 328 sclp_read_req.command = SCLP_CMDW_READ_EVENT_DATA;
298 sclp_read_req.status = SCLP_REQ_QUEUED; 329 sclp_read_req.status = SCLP_REQ_QUEUED;
299 sclp_read_req.start_count = 0; 330 sclp_read_req.start_count = 0;
300 sclp_read_req.callback = sclp_read_cb; 331 sclp_read_req.callback = sclp_read_cb;
@@ -334,6 +365,8 @@ sclp_interrupt_handler(__u16 code)
334 finished_sccb = S390_lowcore.ext_params & 0xfffffff8; 365 finished_sccb = S390_lowcore.ext_params & 0xfffffff8;
335 evbuf_pending = S390_lowcore.ext_params & 0x3; 366 evbuf_pending = S390_lowcore.ext_params & 0x3;
336 if (finished_sccb) { 367 if (finished_sccb) {
368 del_timer(&sclp_request_timer);
369 sclp_running_state = sclp_running_state_reset_pending;
337 req = __sclp_find_req(finished_sccb); 370 req = __sclp_find_req(finished_sccb);
338 if (req) { 371 if (req) {
339 /* Request post-processing */ 372 /* Request post-processing */
@@ -348,13 +381,8 @@ sclp_interrupt_handler(__u16 code)
348 sclp_running_state = sclp_running_state_idle; 381 sclp_running_state = sclp_running_state_idle;
349 } 382 }
350 if (evbuf_pending && sclp_receive_mask != 0 && 383 if (evbuf_pending && sclp_receive_mask != 0 &&
351 sclp_reading_state == sclp_reading_state_idle && 384 sclp_activation_state == sclp_activation_state_active)
352 sclp_activation_state == sclp_activation_state_active ) { 385 __sclp_queue_read_req();
353 sclp_reading_state = sclp_reading_state_reading;
354 __sclp_make_read_req();
355 /* Add request to head of queue */
356 list_add(&sclp_read_req.list, &sclp_req_queue);
357 }
358 spin_unlock(&sclp_lock); 386 spin_unlock(&sclp_lock);
359 sclp_process_queue(); 387 sclp_process_queue();
360} 388}
@@ -374,6 +402,7 @@ sclp_sync_wait(void)
374 unsigned long flags; 402 unsigned long flags;
375 unsigned long cr0, cr0_sync; 403 unsigned long cr0, cr0_sync;
376 u64 timeout; 404 u64 timeout;
405 int irq_context;
377 406
378 /* We'll be disabling timer interrupts, so we need a custom timeout 407 /* We'll be disabling timer interrupts, so we need a custom timeout
379 * mechanism */ 408 * mechanism */
@@ -386,7 +415,9 @@ sclp_sync_wait(void)
386 } 415 }
387 local_irq_save(flags); 416 local_irq_save(flags);
388 /* Prevent bottom half from executing once we force interrupts open */ 417 /* Prevent bottom half from executing once we force interrupts open */
389 local_bh_disable(); 418 irq_context = in_interrupt();
419 if (!irq_context)
420 local_bh_disable();
390 /* Enable service-signal interruption, disable timer interrupts */ 421 /* Enable service-signal interruption, disable timer interrupts */
391 trace_hardirqs_on(); 422 trace_hardirqs_on();
392 __ctl_store(cr0, 0, 0); 423 __ctl_store(cr0, 0, 0);
@@ -402,19 +433,19 @@ sclp_sync_wait(void)
402 get_clock() > timeout && 433 get_clock() > timeout &&
403 del_timer(&sclp_request_timer)) 434 del_timer(&sclp_request_timer))
404 sclp_request_timer.function(sclp_request_timer.data); 435 sclp_request_timer.function(sclp_request_timer.data);
405 barrier();
406 cpu_relax(); 436 cpu_relax();
407 } 437 }
408 local_irq_disable(); 438 local_irq_disable();
409 __ctl_load(cr0, 0, 0); 439 __ctl_load(cr0, 0, 0);
410 _local_bh_enable(); 440 if (!irq_context)
441 _local_bh_enable();
411 local_irq_restore(flags); 442 local_irq_restore(flags);
412} 443}
413 444
414EXPORT_SYMBOL(sclp_sync_wait); 445EXPORT_SYMBOL(sclp_sync_wait);
415 446
416/* Dispatch changes in send and receive mask to registered listeners. */ 447/* Dispatch changes in send and receive mask to registered listeners. */
417static inline void 448static void
418sclp_dispatch_state_change(void) 449sclp_dispatch_state_change(void)
419{ 450{
420 struct list_head *l; 451 struct list_head *l;
@@ -597,7 +628,7 @@ __sclp_make_init_req(u32 receive_mask, u32 send_mask)
597 sccb = (struct init_sccb *) sclp_init_sccb; 628 sccb = (struct init_sccb *) sclp_init_sccb;
598 clear_page(sccb); 629 clear_page(sccb);
599 memset(&sclp_init_req, 0, sizeof(struct sclp_req)); 630 memset(&sclp_init_req, 0, sizeof(struct sclp_req));
600 sclp_init_req.command = SCLP_CMDW_WRITEMASK; 631 sclp_init_req.command = SCLP_CMDW_WRITE_EVENT_MASK;
601 sclp_init_req.status = SCLP_REQ_FILLED; 632 sclp_init_req.status = SCLP_REQ_FILLED;
602 sclp_init_req.start_count = 0; 633 sclp_init_req.start_count = 0;
603 sclp_init_req.callback = NULL; 634 sclp_init_req.callback = NULL;
@@ -800,7 +831,7 @@ sclp_check_interface(void)
800 for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) { 831 for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) {
801 __sclp_make_init_req(0, 0); 832 __sclp_make_init_req(0, 0);
802 sccb = (struct init_sccb *) sclp_init_req.sccb; 833 sccb = (struct init_sccb *) sclp_init_req.sccb;
803 rc = service_call(sclp_init_req.command, sccb); 834 rc = sclp_service_call(sclp_init_req.command, sccb);
804 if (rc == -EIO) 835 if (rc == -EIO)
805 break; 836 break;
806 sclp_init_req.status = SCLP_REQ_RUNNING; 837 sclp_init_req.status = SCLP_REQ_RUNNING;
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index 2c71d6ee7b5b..7d29ab45a6ed 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -12,7 +12,7 @@
12 12
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/list.h> 14#include <linux/list.h>
15 15#include <asm/sclp.h>
16#include <asm/ebcdic.h> 16#include <asm/ebcdic.h>
17 17
18/* maximum number of pages concerning our own memory management */ 18/* maximum number of pages concerning our own memory management */
@@ -49,9 +49,11 @@
49 49
50typedef unsigned int sclp_cmdw_t; 50typedef unsigned int sclp_cmdw_t;
51 51
52#define SCLP_CMDW_READDATA 0x00770005 52#define SCLP_CMDW_READ_EVENT_DATA 0x00770005
53#define SCLP_CMDW_WRITEDATA 0x00760005 53#define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005
54#define SCLP_CMDW_WRITEMASK 0x00780005 54#define SCLP_CMDW_WRITE_EVENT_MASK 0x00780005
55#define SCLP_CMDW_READ_SCP_INFO 0x00020001
56#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
55 57
56#define GDS_ID_MDSMU 0x1310 58#define GDS_ID_MDSMU 0x1310
57#define GDS_ID_MDSRouteInfo 0x1311 59#define GDS_ID_MDSRouteInfo 0x1311
@@ -66,13 +68,6 @@ typedef unsigned int sclp_cmdw_t;
66 68
67typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ 69typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
68 70
69struct sccb_header {
70 u16 length;
71 u8 function_code;
72 u8 control_mask[3];
73 u16 response_code;
74} __attribute__((packed));
75
76struct gds_subvector { 71struct gds_subvector {
77 u8 length; 72 u8 length;
78 u8 key; 73 u8 key;
@@ -131,6 +126,7 @@ void sclp_unregister(struct sclp_register *reg);
131int sclp_remove_processed(struct sccb_header *sccb); 126int sclp_remove_processed(struct sccb_header *sccb);
132int sclp_deactivate(void); 127int sclp_deactivate(void);
133int sclp_reactivate(void); 128int sclp_reactivate(void);
129int sclp_service_call(sclp_cmdw_t command, void *sccb);
134 130
135/* useful inlines */ 131/* useful inlines */
136 132
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c
index 86864f641716..ead1043d788e 100644
--- a/drivers/s390/char/sclp_con.c
+++ b/drivers/s390/char/sclp_con.c
@@ -66,7 +66,7 @@ sclp_conbuf_callback(struct sclp_buffer *buffer, int rc)
66 } while (buffer && sclp_emit_buffer(buffer, sclp_conbuf_callback)); 66 } while (buffer && sclp_emit_buffer(buffer, sclp_conbuf_callback));
67} 67}
68 68
69static inline void 69static void
70sclp_conbuf_emit(void) 70sclp_conbuf_emit(void)
71{ 71{
72 struct sclp_buffer* buffer; 72 struct sclp_buffer* buffer;
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index 4f873ae148b7..65aa2c85737f 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -169,7 +169,7 @@ cpi_prepare_req(void)
169 } 169 }
170 170
171 /* prepare request data structure presented to SCLP driver */ 171 /* prepare request data structure presented to SCLP driver */
172 req->command = SCLP_CMDW_WRITEDATA; 172 req->command = SCLP_CMDW_WRITE_EVENT_DATA;
173 req->sccb = sccb; 173 req->sccb = sccb;
174 req->status = SCLP_REQ_FILLED; 174 req->status = SCLP_REQ_FILLED;
175 req->callback = cpi_callback; 175 req->callback = cpi_callback;
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
new file mode 100644
index 000000000000..7bcbe643b087
--- /dev/null
+++ b/drivers/s390/char/sclp_info.c
@@ -0,0 +1,57 @@
1/*
2 * drivers/s390/char/sclp_info.c
3 *
4 * Copyright IBM Corp. 2007
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
6 */
7
8#include <linux/init.h>
9#include <linux/errno.h>
10#include <linux/string.h>
11#include <asm/sclp.h>
12#include "sclp.h"
13
14struct sclp_readinfo_sccb s390_readinfo_sccb;
15
16void __init sclp_readinfo_early(void)
17{
18 sclp_cmdw_t command;
19 struct sccb_header *sccb;
20 int ret;
21
22 __ctl_set_bit(0, 9); /* enable service signal subclass mask */
23
24 sccb = &s390_readinfo_sccb.header;
25 command = SCLP_CMDW_READ_SCP_INFO_FORCED;
26 while (1) {
27 u16 response;
28
29 memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
30 sccb->length = sizeof(s390_readinfo_sccb);
31 sccb->control_mask[2] = 0x80;
32
33 ret = sclp_service_call(command, &s390_readinfo_sccb);
34
35 if (ret == -EIO)
36 goto out;
37 if (ret == -EBUSY)
38 continue;
39
40 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
41 PSW_MASK_WAIT | PSW_DEFAULT_KEY);
42 local_irq_disable();
43 barrier();
44
45 response = sccb->response_code;
46
47 if (response == 0x10)
48 break;
49
50 if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
51 break;
52
53 command = SCLP_CMDW_READ_SCP_INFO;
54 }
55out:
56 __ctl_clear_bit(0, 9); /* disable service signal subclass mask */
57}
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index 0c92d3909cca..2486783ea58e 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -460,7 +460,7 @@ sclp_emit_buffer(struct sclp_buffer *buffer,
460 sccb->msg_buf.header.type = EvTyp_PMsgCmd; 460 sccb->msg_buf.header.type = EvTyp_PMsgCmd;
461 else 461 else
462 return -ENOSYS; 462 return -ENOSYS;
463 buffer->request.command = SCLP_CMDW_WRITEDATA; 463 buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA;
464 buffer->request.status = SCLP_REQ_FILLED; 464 buffer->request.status = SCLP_REQ_FILLED;
465 buffer->request.callback = sclp_writedata_callback; 465 buffer->request.callback = sclp_writedata_callback;
466 buffer->request.callback_data = buffer; 466 buffer->request.callback_data = buffer;
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 2d173e5c8a09..90536f60bf50 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -721,7 +721,7 @@ static const struct tty_operations sclp_ops = {
721 .ioctl = sclp_tty_ioctl, 721 .ioctl = sclp_tty_ioctl,
722}; 722};
723 723
724int __init 724static int __init
725sclp_tty_init(void) 725sclp_tty_init(void)
726{ 726{
727 struct tty_driver *driver; 727 struct tty_driver *driver;
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 723bf4191bfe..544f137d70d7 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -207,7 +207,7 @@ __sclp_vt220_emit(struct sclp_vt220_request *request)
207 request->sclp_req.status = SCLP_REQ_FAILED; 207 request->sclp_req.status = SCLP_REQ_FAILED;
208 return -EIO; 208 return -EIO;
209 } 209 }
210 request->sclp_req.command = SCLP_CMDW_WRITEDATA; 210 request->sclp_req.command = SCLP_CMDW_WRITE_EVENT_DATA;
211 request->sclp_req.status = SCLP_REQ_FILLED; 211 request->sclp_req.status = SCLP_REQ_FILLED;
212 request->sclp_req.callback = sclp_vt220_callback; 212 request->sclp_req.callback = sclp_vt220_callback;
213 request->sclp_req.callback_data = (void *) request; 213 request->sclp_req.callback_data = (void *) request;
@@ -669,7 +669,7 @@ static const struct tty_operations sclp_vt220_ops = {
669/* 669/*
670 * Register driver with SCLP and Linux and initialize internal tty structures. 670 * Register driver with SCLP and Linux and initialize internal tty structures.
671 */ 671 */
672int __init 672static int __init
673sclp_vt220_tty_init(void) 673sclp_vt220_tty_init(void)
674{ 674{
675 struct tty_driver *driver; 675 struct tty_driver *driver;
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index c9f1c4c8bb13..bb4ff537729d 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -3,7 +3,7 @@
3 * tape device driver for 3480/3490E/3590 tapes. 3 * tape device driver for 3480/3490E/3590 tapes.
4 * 4 *
5 * S390 and zSeries version 5 * S390 and zSeries version
6 * Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Copyright IBM Corp. 2001,2006
7 * Author(s): Carsten Otte <cotte@de.ibm.com> 7 * Author(s): Carsten Otte <cotte@de.ibm.com>
8 * Tuan Ngo-Anh <ngoanh@de.ibm.com> 8 * Tuan Ngo-Anh <ngoanh@de.ibm.com>
9 * Martin Schwidefsky <schwidefsky@de.ibm.com> 9 * Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -99,7 +99,11 @@ enum tape_op {
99 TO_DIS, /* Tape display */ 99 TO_DIS, /* Tape display */
100 TO_ASSIGN, /* Assign tape to channel path */ 100 TO_ASSIGN, /* Assign tape to channel path */
101 TO_UNASSIGN, /* Unassign tape from channel path */ 101 TO_UNASSIGN, /* Unassign tape from channel path */
102 TO_SIZE /* #entries in tape_op_t */ 102 TO_CRYPT_ON, /* Enable encrpytion */
103 TO_CRYPT_OFF, /* Disable encrpytion */
104 TO_KEKL_SET, /* Set KEK label */
105 TO_KEKL_QUERY, /* Query KEK label */
106 TO_SIZE, /* #entries in tape_op_t */
103}; 107};
104 108
105/* Forward declaration */ 109/* Forward declaration */
@@ -112,6 +116,7 @@ enum tape_request_status {
112 TAPE_REQUEST_IN_IO, /* request is currently in IO */ 116 TAPE_REQUEST_IN_IO, /* request is currently in IO */
113 TAPE_REQUEST_DONE, /* request is completed. */ 117 TAPE_REQUEST_DONE, /* request is completed. */
114 TAPE_REQUEST_CANCEL, /* request should be canceled. */ 118 TAPE_REQUEST_CANCEL, /* request should be canceled. */
119 TAPE_REQUEST_LONG_BUSY, /* request has to be restarted after long busy */
115}; 120};
116 121
117/* Tape CCW request */ 122/* Tape CCW request */
@@ -164,10 +169,11 @@ struct tape_discipline {
164 * The discipline irq function either returns an error code (<0) which 169 * The discipline irq function either returns an error code (<0) which
165 * means that the request has failed with an error or one of the following: 170 * means that the request has failed with an error or one of the following:
166 */ 171 */
167#define TAPE_IO_SUCCESS 0 /* request successful */ 172#define TAPE_IO_SUCCESS 0 /* request successful */
168#define TAPE_IO_PENDING 1 /* request still running */ 173#define TAPE_IO_PENDING 1 /* request still running */
169#define TAPE_IO_RETRY 2 /* retry to current request */ 174#define TAPE_IO_RETRY 2 /* retry to current request */
170#define TAPE_IO_STOP 3 /* stop the running request */ 175#define TAPE_IO_STOP 3 /* stop the running request */
176#define TAPE_IO_LONG_BUSY 4 /* delay the running request */
171 177
172/* Char Frontend Data */ 178/* Char Frontend Data */
173struct tape_char_data { 179struct tape_char_data {
@@ -242,6 +248,10 @@ struct tape_device {
242 248
243 /* Function to start or stop the next request later. */ 249 /* Function to start or stop the next request later. */
244 struct delayed_work tape_dnr; 250 struct delayed_work tape_dnr;
251
252 /* Timer for long busy */
253 struct timer_list lb_timeout;
254
245}; 255};
246 256
247/* Externals from tape_core.c */ 257/* Externals from tape_core.c */
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 9df912f63188..50f5edab83d7 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -2,7 +2,7 @@
2 * drivers/s390/char/tape_3590.c 2 * drivers/s390/char/tape_3590.c
3 * tape device discipline for 3590 tapes. 3 * tape device discipline for 3590 tapes.
4 * 4 *
5 * Copyright (C) IBM Corp. 2001,2006 5 * Copyright IBM Corp. 2001,2006
6 * Author(s): Stefan Bader <shbader@de.ibm.com> 6 * Author(s): Stefan Bader <shbader@de.ibm.com>
7 * Michael Holzheu <holzheu@de.ibm.com> 7 * Michael Holzheu <holzheu@de.ibm.com>
8 * Martin Schwidefsky <schwidefsky@de.ibm.com> 8 * Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -11,6 +11,7 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/bio.h> 13#include <linux/bio.h>
14#include <asm/ebcdic.h>
14 15
15#define TAPE_DBF_AREA tape_3590_dbf 16#define TAPE_DBF_AREA tape_3590_dbf
16 17
@@ -30,7 +31,7 @@ EXPORT_SYMBOL(TAPE_DBF_AREA);
30 * - Read Device (buffered) log: BRA 31 * - Read Device (buffered) log: BRA
31 * - Read Library log: BRA 32 * - Read Library log: BRA
32 * - Swap Devices: BRA 33 * - Swap Devices: BRA
33 * - Long Busy: BRA 34 * - Long Busy: implemented
34 * - Special Intercept: BRA 35 * - Special Intercept: BRA
35 * - Read Alternate: implemented 36 * - Read Alternate: implemented
36 *******************************************************************/ 37 *******************************************************************/
@@ -94,6 +95,332 @@ static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = {
94 [0xae] = "Subsystem environmental alert", 95 [0xae] = "Subsystem environmental alert",
95}; 96};
96 97
98static int crypt_supported(struct tape_device *device)
99{
100 return TAPE390_CRYPT_SUPPORTED(TAPE_3590_CRYPT_INFO(device));
101}
102
103static int crypt_enabled(struct tape_device *device)
104{
105 return TAPE390_CRYPT_ON(TAPE_3590_CRYPT_INFO(device));
106}
107
108static void ext_to_int_kekl(struct tape390_kekl *in,
109 struct tape3592_kekl *out)
110{
111 int i;
112
113 memset(out, 0, sizeof(*out));
114 if (in->type == TAPE390_KEKL_TYPE_HASH)
115 out->flags |= 0x40;
116 if (in->type_on_tape == TAPE390_KEKL_TYPE_HASH)
117 out->flags |= 0x80;
118 strncpy(out->label, in->label, 64);
119 for (i = strlen(in->label); i < sizeof(out->label); i++)
120 out->label[i] = ' ';
121 ASCEBC(out->label, sizeof(out->label));
122}
123
124static void int_to_ext_kekl(struct tape3592_kekl *in,
125 struct tape390_kekl *out)
126{
127 memset(out, 0, sizeof(*out));
128 if(in->flags & 0x40)
129 out->type = TAPE390_KEKL_TYPE_HASH;
130 else
131 out->type = TAPE390_KEKL_TYPE_LABEL;
132 if(in->flags & 0x80)
133 out->type_on_tape = TAPE390_KEKL_TYPE_HASH;
134 else
135 out->type_on_tape = TAPE390_KEKL_TYPE_LABEL;
136 memcpy(out->label, in->label, sizeof(in->label));
137 EBCASC(out->label, sizeof(in->label));
138 strstrip(out->label);
139}
140
141static void int_to_ext_kekl_pair(struct tape3592_kekl_pair *in,
142 struct tape390_kekl_pair *out)
143{
144 if (in->count == 0) {
145 out->kekl[0].type = TAPE390_KEKL_TYPE_NONE;
146 out->kekl[0].type_on_tape = TAPE390_KEKL_TYPE_NONE;
147 out->kekl[1].type = TAPE390_KEKL_TYPE_NONE;
148 out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE;
149 } else if (in->count == 1) {
150 int_to_ext_kekl(&in->kekl[0], &out->kekl[0]);
151 out->kekl[1].type = TAPE390_KEKL_TYPE_NONE;
152 out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE;
153 } else if (in->count == 2) {
154 int_to_ext_kekl(&in->kekl[0], &out->kekl[0]);
155 int_to_ext_kekl(&in->kekl[1], &out->kekl[1]);
156 } else {
157 printk("Invalid KEKL number: %d\n", in->count);
158 BUG();
159 }
160}
161
162static int check_ext_kekl(struct tape390_kekl *kekl)
163{
164 if (kekl->type == TAPE390_KEKL_TYPE_NONE)
165 goto invalid;
166 if (kekl->type > TAPE390_KEKL_TYPE_HASH)
167 goto invalid;
168 if (kekl->type_on_tape == TAPE390_KEKL_TYPE_NONE)
169 goto invalid;
170 if (kekl->type_on_tape > TAPE390_KEKL_TYPE_HASH)
171 goto invalid;
172 if ((kekl->type == TAPE390_KEKL_TYPE_HASH) &&
173 (kekl->type_on_tape == TAPE390_KEKL_TYPE_LABEL))
174 goto invalid;
175
176 return 0;
177invalid:
178 return -EINVAL;
179}
180
181static int check_ext_kekl_pair(struct tape390_kekl_pair *kekls)
182{
183 if (check_ext_kekl(&kekls->kekl[0]))
184 goto invalid;
185 if (check_ext_kekl(&kekls->kekl[1]))
186 goto invalid;
187
188 return 0;
189invalid:
190 return -EINVAL;
191}
192
193/*
194 * Query KEKLs
195 */
196static int tape_3592_kekl_query(struct tape_device *device,
197 struct tape390_kekl_pair *ext_kekls)
198{
199 struct tape_request *request;
200 struct tape3592_kekl_query_order *order;
201 struct tape3592_kekl_query_data *int_kekls;
202 int rc;
203
204 DBF_EVENT(6, "tape3592_kekl_query\n");
205 int_kekls = kmalloc(sizeof(*int_kekls), GFP_KERNEL|GFP_DMA);
206 if (!int_kekls)
207 return -ENOMEM;
208 request = tape_alloc_request(2, sizeof(*order));
209 if (IS_ERR(request)) {
210 rc = PTR_ERR(request);
211 goto fail_malloc;
212 }
213 order = request->cpdata;
214 memset(order,0,sizeof(*order));
215 order->code = 0xe2;
216 order->max_count = 2;
217 request->op = TO_KEKL_QUERY;
218 tape_ccw_cc(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order);
219 tape_ccw_end(request->cpaddr + 1, READ_SS_DATA, sizeof(*int_kekls),
220 int_kekls);
221 rc = tape_do_io(device, request);
222 if (rc)
223 goto fail_request;
224 int_to_ext_kekl_pair(&int_kekls->kekls, ext_kekls);
225
226 rc = 0;
227fail_request:
228 tape_free_request(request);
229fail_malloc:
230 kfree(int_kekls);
231 return rc;
232}
233
234/*
235 * IOCTL: Query KEKLs
236 */
237static int tape_3592_ioctl_kekl_query(struct tape_device *device,
238 unsigned long arg)
239{
240 int rc;
241 struct tape390_kekl_pair *ext_kekls;
242
243 DBF_EVENT(6, "tape_3592_ioctl_kekl_query\n");
244 if (!crypt_supported(device))
245 return -ENOSYS;
246 if (!crypt_enabled(device))
247 return -EUNATCH;
248 ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL);
249 if (!ext_kekls)
250 return -ENOMEM;
251 rc = tape_3592_kekl_query(device, ext_kekls);
252 if (rc != 0)
253 goto fail;
254 if (copy_to_user((char __user *) arg, ext_kekls, sizeof(*ext_kekls))) {
255 rc = -EFAULT;
256 goto fail;
257 }
258 rc = 0;
259fail:
260 kfree(ext_kekls);
261 return rc;
262}
263
264static int tape_3590_mttell(struct tape_device *device, int mt_count);
265
266/*
267 * Set KEKLs
268 */
269static int tape_3592_kekl_set(struct tape_device *device,
270 struct tape390_kekl_pair *ext_kekls)
271{
272 struct tape_request *request;
273 struct tape3592_kekl_set_order *order;
274
275 DBF_EVENT(6, "tape3592_kekl_set\n");
276 if (check_ext_kekl_pair(ext_kekls)) {
277 DBF_EVENT(6, "invalid kekls\n");
278 return -EINVAL;
279 }
280 if (tape_3590_mttell(device, 0) != 0)
281 return -EBADSLT;
282 request = tape_alloc_request(1, sizeof(*order));
283 if (IS_ERR(request))
284 return PTR_ERR(request);
285 order = request->cpdata;
286 memset(order, 0, sizeof(*order));
287 order->code = 0xe3;
288 order->kekls.count = 2;
289 ext_to_int_kekl(&ext_kekls->kekl[0], &order->kekls.kekl[0]);
290 ext_to_int_kekl(&ext_kekls->kekl[1], &order->kekls.kekl[1]);
291 request->op = TO_KEKL_SET;
292 tape_ccw_end(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order);
293
294 return tape_do_io_free(device, request);
295}
296
297/*
298 * IOCTL: Set KEKLs
299 */
300static int tape_3592_ioctl_kekl_set(struct tape_device *device,
301 unsigned long arg)
302{
303 int rc;
304 struct tape390_kekl_pair *ext_kekls;
305
306 DBF_EVENT(6, "tape_3592_ioctl_kekl_set\n");
307 if (!crypt_supported(device))
308 return -ENOSYS;
309 if (!crypt_enabled(device))
310 return -EUNATCH;
311 ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL);
312 if (!ext_kekls)
313 return -ENOMEM;
314 if (copy_from_user(ext_kekls, (char __user *)arg, sizeof(*ext_kekls))) {
315 rc = -EFAULT;
316 goto out;
317 }
318 rc = tape_3592_kekl_set(device, ext_kekls);
319out:
320 kfree(ext_kekls);
321 return rc;
322}
323
324/*
325 * Enable encryption
326 */
327static int tape_3592_enable_crypt(struct tape_device *device)
328{
329 struct tape_request *request;
330 char *data;
331
332 DBF_EVENT(6, "tape_3592_enable_crypt\n");
333 if (!crypt_supported(device))
334 return -ENOSYS;
335 request = tape_alloc_request(2, 72);
336 if (IS_ERR(request))
337 return PTR_ERR(request);
338 data = request->cpdata;
339 memset(data,0,72);
340
341 data[0] = 0x05;
342 data[36 + 0] = 0x03;
343 data[36 + 1] = 0x03;
344 data[36 + 4] = 0x40;
345 data[36 + 6] = 0x01;
346 data[36 + 14] = 0x2f;
347 data[36 + 18] = 0xc3;
348 data[36 + 35] = 0x72;
349 request->op = TO_CRYPT_ON;
350 tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
351 tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
352 return tape_do_io_free(device, request);
353}
354
355/*
356 * Disable encryption
357 */
358static int tape_3592_disable_crypt(struct tape_device *device)
359{
360 struct tape_request *request;
361 char *data;
362
363 DBF_EVENT(6, "tape_3592_disable_crypt\n");
364 if (!crypt_supported(device))
365 return -ENOSYS;
366 request = tape_alloc_request(2, 72);
367 if (IS_ERR(request))
368 return PTR_ERR(request);
369 data = request->cpdata;
370 memset(data,0,72);
371
372 data[0] = 0x05;
373 data[36 + 0] = 0x03;
374 data[36 + 1] = 0x03;
375 data[36 + 35] = 0x32;
376
377 request->op = TO_CRYPT_OFF;
378 tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
379 tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
380
381 return tape_do_io_free(device, request);
382}
383
384/*
385 * IOCTL: Set encryption status
386 */
387static int tape_3592_ioctl_crypt_set(struct tape_device *device,
388 unsigned long arg)
389{
390 struct tape390_crypt_info info;
391
392 DBF_EVENT(6, "tape_3592_ioctl_crypt_set\n");
393 if (!crypt_supported(device))
394 return -ENOSYS;
395 if (copy_from_user(&info, (char __user *)arg, sizeof(info)))
396 return -EFAULT;
397 if (info.status & ~TAPE390_CRYPT_ON_MASK)
398 return -EINVAL;
399 if (info.status & TAPE390_CRYPT_ON_MASK)
400 return tape_3592_enable_crypt(device);
401 else
402 return tape_3592_disable_crypt(device);
403}
404
405static int tape_3590_sense_medium(struct tape_device *device);
406
407/*
408 * IOCTL: Query enryption status
409 */
410static int tape_3592_ioctl_crypt_query(struct tape_device *device,
411 unsigned long arg)
412{
413 DBF_EVENT(6, "tape_3592_ioctl_crypt_query\n");
414 if (!crypt_supported(device))
415 return -ENOSYS;
416 tape_3590_sense_medium(device);
417 if (copy_to_user((char __user *) arg, &TAPE_3590_CRYPT_INFO(device),
418 sizeof(TAPE_3590_CRYPT_INFO(device))))
419 return -EFAULT;
420 else
421 return 0;
422}
423
97/* 424/*
98 * 3590 IOCTL Overload 425 * 3590 IOCTL Overload
99 */ 426 */
@@ -109,6 +436,14 @@ tape_3590_ioctl(struct tape_device *device, unsigned int cmd, unsigned long arg)
109 436
110 return tape_std_display(device, &disp); 437 return tape_std_display(device, &disp);
111 } 438 }
439 case TAPE390_KEKL_SET:
440 return tape_3592_ioctl_kekl_set(device, arg);
441 case TAPE390_KEKL_QUERY:
442 return tape_3592_ioctl_kekl_query(device, arg);
443 case TAPE390_CRYPT_SET:
444 return tape_3592_ioctl_crypt_set(device, arg);
445 case TAPE390_CRYPT_QUERY:
446 return tape_3592_ioctl_crypt_query(device, arg);
112 default: 447 default:
113 return -EINVAL; /* no additional ioctls */ 448 return -EINVAL; /* no additional ioctls */
114 } 449 }
@@ -248,6 +583,12 @@ tape_3590_work_handler(struct work_struct *work)
248 case TO_READ_ATTMSG: 583 case TO_READ_ATTMSG:
249 tape_3590_read_attmsg(p->device); 584 tape_3590_read_attmsg(p->device);
250 break; 585 break;
586 case TO_CRYPT_ON:
587 tape_3592_enable_crypt(p->device);
588 break;
589 case TO_CRYPT_OFF:
590 tape_3592_disable_crypt(p->device);
591 break;
251 default: 592 default:
252 DBF_EVENT(3, "T3590: work handler undefined for " 593 DBF_EVENT(3, "T3590: work handler undefined for "
253 "operation 0x%02x\n", p->op); 594 "operation 0x%02x\n", p->op);
@@ -365,6 +706,33 @@ tape_3590_check_locate(struct tape_device *device, struct tape_request *request)
365} 706}
366#endif 707#endif
367 708
709static void tape_3590_med_state_set(struct tape_device *device,
710 struct tape_3590_med_sense *sense)
711{
712 struct tape390_crypt_info *c_info;
713
714 c_info = &TAPE_3590_CRYPT_INFO(device);
715
716 if (sense->masst == MSENSE_UNASSOCIATED) {
717 tape_med_state_set(device, MS_UNLOADED);
718 TAPE_3590_CRYPT_INFO(device).medium_status = 0;
719 return;
720 }
721 if (sense->masst != MSENSE_ASSOCIATED_MOUNT) {
722 PRINT_ERR("Unknown medium state: %x\n", sense->masst);
723 return;
724 }
725 tape_med_state_set(device, MS_LOADED);
726 c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK;
727 if (sense->flags & MSENSE_CRYPT_MASK) {
728 PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags);
729 c_info->medium_status |= TAPE390_MEDIUM_ENCRYPTED_MASK;
730 } else {
731 DBF_EVENT(6, "Medium is not encrypted %04x\n", sense->flags);
732 c_info->medium_status &= ~TAPE390_MEDIUM_ENCRYPTED_MASK;
733 }
734}
735
368/* 736/*
369 * The done handler is called at device/channel end and wakes up the sleeping 737 * The done handler is called at device/channel end and wakes up the sleeping
370 * process 738 * process
@@ -372,9 +740,10 @@ tape_3590_check_locate(struct tape_device *device, struct tape_request *request)
372static int 740static int
373tape_3590_done(struct tape_device *device, struct tape_request *request) 741tape_3590_done(struct tape_device *device, struct tape_request *request)
374{ 742{
375 struct tape_3590_med_sense *sense; 743 struct tape_3590_disc_data *disc_data;
376 744
377 DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]); 745 DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]);
746 disc_data = device->discdata;
378 747
379 switch (request->op) { 748 switch (request->op) {
380 case TO_BSB: 749 case TO_BSB:
@@ -394,13 +763,20 @@ tape_3590_done(struct tape_device *device, struct tape_request *request)
394 break; 763 break;
395 case TO_RUN: 764 case TO_RUN:
396 tape_med_state_set(device, MS_UNLOADED); 765 tape_med_state_set(device, MS_UNLOADED);
766 tape_3590_schedule_work(device, TO_CRYPT_OFF);
397 break; 767 break;
398 case TO_MSEN: 768 case TO_MSEN:
399 sense = (struct tape_3590_med_sense *) request->cpdata; 769 tape_3590_med_state_set(device, request->cpdata);
400 if (sense->masst == MSENSE_UNASSOCIATED) 770 break;
401 tape_med_state_set(device, MS_UNLOADED); 771 case TO_CRYPT_ON:
402 if (sense->masst == MSENSE_ASSOCIATED_MOUNT) 772 TAPE_3590_CRYPT_INFO(device).status
403 tape_med_state_set(device, MS_LOADED); 773 |= TAPE390_CRYPT_ON_MASK;
774 *(device->modeset_byte) |= 0x03;
775 break;
776 case TO_CRYPT_OFF:
777 TAPE_3590_CRYPT_INFO(device).status
778 &= ~TAPE390_CRYPT_ON_MASK;
779 *(device->modeset_byte) &= ~0x03;
404 break; 780 break;
405 case TO_RBI: /* RBI seems to succeed even without medium loaded. */ 781 case TO_RBI: /* RBI seems to succeed even without medium loaded. */
406 case TO_NOP: /* Same to NOP. */ 782 case TO_NOP: /* Same to NOP. */
@@ -409,8 +785,9 @@ tape_3590_done(struct tape_device *device, struct tape_request *request)
409 case TO_DIS: 785 case TO_DIS:
410 case TO_ASSIGN: 786 case TO_ASSIGN:
411 case TO_UNASSIGN: 787 case TO_UNASSIGN:
412 break;
413 case TO_SIZE: 788 case TO_SIZE:
789 case TO_KEKL_SET:
790 case TO_KEKL_QUERY:
414 break; 791 break;
415 } 792 }
416 return TAPE_IO_SUCCESS; 793 return TAPE_IO_SUCCESS;
@@ -540,10 +917,8 @@ static int
540tape_3590_erp_long_busy(struct tape_device *device, 917tape_3590_erp_long_busy(struct tape_device *device,
541 struct tape_request *request, struct irb *irb) 918 struct tape_request *request, struct irb *irb)
542{ 919{
543 /* FIXME: how about WAITING for a minute ? */ 920 DBF_EVENT(6, "Device is busy\n");
544 PRINT_WARN("(%s): Device is busy! Please wait a minute!\n", 921 return TAPE_IO_LONG_BUSY;
545 device->cdev->dev.bus_id);
546 return tape_3590_erp_basic(device, request, irb, -EBUSY);
547} 922}
548 923
549/* 924/*
@@ -951,6 +1326,34 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
951 device->cdev->dev.bus_id, sense->mc); 1326 device->cdev->dev.bus_id, sense->mc);
952} 1327}
953 1328
1329static int tape_3590_crypt_error(struct tape_device *device,
1330 struct tape_request *request, struct irb *irb)
1331{
1332 u8 cu_rc, ekm_rc1;
1333 u16 ekm_rc2;
1334 u32 drv_rc;
1335 char *bus_id, *sense;
1336
1337 sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data;
1338 bus_id = device->cdev->dev.bus_id;
1339 cu_rc = sense[0];
1340 drv_rc = *((u32*) &sense[5]) & 0xffffff;
1341 ekm_rc1 = sense[9];
1342 ekm_rc2 = *((u16*) &sense[10]);
1343 if ((cu_rc == 0) && (ekm_rc2 == 0xee31))
1344 /* key not defined on EKM */
1345 return tape_3590_erp_basic(device, request, irb, -EKEYREJECTED);
1346 if ((cu_rc == 1) || (cu_rc == 2))
1347 /* No connection to EKM */
1348 return tape_3590_erp_basic(device, request, irb, -ENOTCONN);
1349
1350 PRINT_ERR("(%s): Unable to get encryption key from EKM\n", bus_id);
1351 PRINT_ERR("(%s): CU=%02X DRIVE=%06X EKM=%02X:%04X\n", bus_id, cu_rc,
1352 drv_rc, ekm_rc1, ekm_rc2);
1353
1354 return tape_3590_erp_basic(device, request, irb, -ENOKEY);
1355}
1356
954/* 1357/*
955 * 3590 error Recovery routine: 1358 * 3590 error Recovery routine:
956 * If possible, it tries to recover from the error. If this is not possible, 1359 * If possible, it tries to recover from the error. If this is not possible,
@@ -979,6 +1382,8 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
979 1382
980 sense = (struct tape_3590_sense *) irb->ecw; 1383 sense = (struct tape_3590_sense *) irb->ecw;
981 1384
1385 DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc);
1386
982 /* 1387 /*
983 * First check all RC-QRCs where we want to do something special 1388 * First check all RC-QRCs where we want to do something special
984 * - "break": basic error recovery is done 1389 * - "break": basic error recovery is done
@@ -999,6 +1404,8 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
999 case 0x2231: 1404 case 0x2231:
1000 tape_3590_print_era_msg(device, irb); 1405 tape_3590_print_era_msg(device, irb);
1001 return tape_3590_erp_special_interrupt(device, request, irb); 1406 return tape_3590_erp_special_interrupt(device, request, irb);
1407 case 0x2240:
1408 return tape_3590_crypt_error(device, request, irb);
1002 1409
1003 case 0x3010: 1410 case 0x3010:
1004 DBF_EVENT(2, "(%08x): Backward at Beginning of Partition\n", 1411 DBF_EVENT(2, "(%08x): Backward at Beginning of Partition\n",
@@ -1020,6 +1427,7 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
1020 DBF_EVENT(2, "(%08x): Rewind Unload complete\n", 1427 DBF_EVENT(2, "(%08x): Rewind Unload complete\n",
1021 device->cdev_id); 1428 device->cdev_id);
1022 tape_med_state_set(device, MS_UNLOADED); 1429 tape_med_state_set(device, MS_UNLOADED);
1430 tape_3590_schedule_work(device, TO_CRYPT_OFF);
1023 return tape_3590_erp_basic(device, request, irb, 0); 1431 return tape_3590_erp_basic(device, request, irb, 0);
1024 1432
1025 case 0x4010: 1433 case 0x4010:
@@ -1030,9 +1438,15 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
1030 PRINT_WARN("(%s): Tape operation when medium not loaded\n", 1438 PRINT_WARN("(%s): Tape operation when medium not loaded\n",
1031 device->cdev->dev.bus_id); 1439 device->cdev->dev.bus_id);
1032 tape_med_state_set(device, MS_UNLOADED); 1440 tape_med_state_set(device, MS_UNLOADED);
1441 tape_3590_schedule_work(device, TO_CRYPT_OFF);
1033 return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); 1442 return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);
1034 case 0x4012: /* Device Long Busy */ 1443 case 0x4012: /* Device Long Busy */
1444 /* XXX: Also use long busy handling here? */
1445 DBF_EVENT(6, "(%08x): LONG BUSY\n", device->cdev_id);
1035 tape_3590_print_era_msg(device, irb); 1446 tape_3590_print_era_msg(device, irb);
1447 return tape_3590_erp_basic(device, request, irb, -EBUSY);
1448 case 0x4014:
1449 DBF_EVENT(6, "(%08x): Crypto LONG BUSY\n", device->cdev_id);
1036 return tape_3590_erp_long_busy(device, request, irb); 1450 return tape_3590_erp_long_busy(device, request, irb);
1037 1451
1038 case 0x5010: 1452 case 0x5010:
@@ -1064,6 +1478,7 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
1064 case 0x5120: 1478 case 0x5120:
1065 case 0x1120: 1479 case 0x1120:
1066 tape_med_state_set(device, MS_UNLOADED); 1480 tape_med_state_set(device, MS_UNLOADED);
1481 tape_3590_schedule_work(device, TO_CRYPT_OFF);
1067 return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); 1482 return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);
1068 1483
1069 case 0x6020: 1484 case 0x6020:
@@ -1142,21 +1557,47 @@ tape_3590_setup_device(struct tape_device *device)
1142{ 1557{
1143 int rc; 1558 int rc;
1144 struct tape_3590_disc_data *data; 1559 struct tape_3590_disc_data *data;
1560 char *rdc_data;
1145 1561
1146 DBF_EVENT(6, "3590 device setup\n"); 1562 DBF_EVENT(6, "3590 device setup\n");
1147 data = kmalloc(sizeof(struct tape_3590_disc_data), 1563 data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA);
1148 GFP_KERNEL | GFP_DMA);
1149 if (data == NULL) 1564 if (data == NULL)
1150 return -ENOMEM; 1565 return -ENOMEM;
1151 data->read_back_op = READ_PREVIOUS; 1566 data->read_back_op = READ_PREVIOUS;
1152 device->discdata = data; 1567 device->discdata = data;
1153 1568
1154 if ((rc = tape_std_assign(device)) == 0) { 1569 rdc_data = kmalloc(64, GFP_KERNEL | GFP_DMA);
1155 /* Try to find out if medium is loaded */ 1570 if (!rdc_data) {
1156 if ((rc = tape_3590_sense_medium(device)) != 0) 1571 rc = -ENOMEM;
1157 DBF_LH(3, "3590 medium sense returned %d\n", rc); 1572 goto fail_kmalloc;
1573 }
1574 rc = read_dev_chars(device->cdev, (void**)&rdc_data, 64);
1575 if (rc) {
1576 DBF_LH(3, "Read device characteristics failed!\n");
1577 goto fail_kmalloc;
1578 }
1579 rc = tape_std_assign(device);
1580 if (rc)
1581 goto fail_rdc_data;
1582 if (rdc_data[31] == 0x13) {
1583 PRINT_INFO("Device has crypto support\n");
1584 data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK;
1585 tape_3592_disable_crypt(device);
1586 } else {
1587 DBF_EVENT(6, "Device has NO crypto support\n");
1158 } 1588 }
1589 /* Try to find out if medium is loaded */
1590 rc = tape_3590_sense_medium(device);
1591 if (rc) {
1592 DBF_LH(3, "3590 medium sense returned %d\n", rc);
1593 goto fail_rdc_data;
1594 }
1595 return 0;
1159 1596
1597fail_rdc_data:
1598 kfree(rdc_data);
1599fail_kmalloc:
1600 kfree(data);
1160 return rc; 1601 return rc;
1161} 1602}
1162 1603
diff --git a/drivers/s390/char/tape_3590.h b/drivers/s390/char/tape_3590.h
index cf274b9445a6..aa5138807af1 100644
--- a/drivers/s390/char/tape_3590.h
+++ b/drivers/s390/char/tape_3590.h
@@ -2,7 +2,7 @@
2 * drivers/s390/char/tape_3590.h 2 * drivers/s390/char/tape_3590.h
3 * tape device discipline for 3590 tapes. 3 * tape device discipline for 3590 tapes.
4 * 4 *
5 * Copyright (C) IBM Corp. 2001,2006 5 * Copyright IBM Corp. 2001,2006
6 * Author(s): Stefan Bader <shbader@de.ibm.com> 6 * Author(s): Stefan Bader <shbader@de.ibm.com>
7 * Michael Holzheu <holzheu@de.ibm.com> 7 * Michael Holzheu <holzheu@de.ibm.com>
8 * Martin Schwidefsky <schwidefsky@de.ibm.com> 8 * Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -38,16 +38,22 @@
38#define MSENSE_UNASSOCIATED 0x00 38#define MSENSE_UNASSOCIATED 0x00
39#define MSENSE_ASSOCIATED_MOUNT 0x01 39#define MSENSE_ASSOCIATED_MOUNT 0x01
40#define MSENSE_ASSOCIATED_UMOUNT 0x02 40#define MSENSE_ASSOCIATED_UMOUNT 0x02
41#define MSENSE_CRYPT_MASK 0x00000010
41 42
42#define TAPE_3590_MAX_MSG 0xb0 43#define TAPE_3590_MAX_MSG 0xb0
43 44
44/* Datatypes */ 45/* Datatypes */
45 46
46struct tape_3590_disc_data { 47struct tape_3590_disc_data {
47 unsigned char modeset_byte; 48 struct tape390_crypt_info crypt_info;
48 int read_back_op; 49 int read_back_op;
49}; 50};
50 51
52#define TAPE_3590_CRYPT_INFO(device) \
53 ((struct tape_3590_disc_data*)(device->discdata))->crypt_info
54#define TAPE_3590_READ_BACK_OP(device) \
55 ((struct tape_3590_disc_data*)(device->discdata))->read_back_op
56
51struct tape_3590_sense { 57struct tape_3590_sense {
52 58
53 unsigned int command_rej:1; 59 unsigned int command_rej:1;
@@ -118,7 +124,48 @@ struct tape_3590_sense {
118struct tape_3590_med_sense { 124struct tape_3590_med_sense {
119 unsigned int macst:4; 125 unsigned int macst:4;
120 unsigned int masst:4; 126 unsigned int masst:4;
121 char pad[127]; 127 char pad1[7];
128 unsigned int flags;
129 char pad2[116];
130} __attribute__ ((packed));
131
132/* Datastructures for 3592 encryption support */
133
134struct tape3592_kekl {
135 __u8 flags;
136 char label[64];
137} __attribute__ ((packed));
138
139struct tape3592_kekl_pair {
140 __u8 count;
141 struct tape3592_kekl kekl[2];
142} __attribute__ ((packed));
143
144struct tape3592_kekl_query_data {
145 __u16 len;
146 __u8 fmt;
147 __u8 mc;
148 __u32 id;
149 __u8 flags;
150 struct tape3592_kekl_pair kekls;
151 char reserved[116];
152} __attribute__ ((packed));
153
154struct tape3592_kekl_query_order {
155 __u8 code;
156 __u8 flags;
157 char reserved1[2];
158 __u8 max_count;
159 char reserved2[35];
160} __attribute__ ((packed));
161
162struct tape3592_kekl_set_order {
163 __u8 code;
164 __u8 flags;
165 char reserved1[2];
166 __u8 op;
167 struct tape3592_kekl_pair kekls;
168 char reserved2[120];
122} __attribute__ ((packed)); 169} __attribute__ ((packed));
123 170
124#endif /* _TAPE_3590_H */ 171#endif /* _TAPE_3590_H */
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index c8a89b3b87d4..dd0ecaed592e 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -73,7 +73,7 @@ tapeblock_trigger_requeue(struct tape_device *device)
73/* 73/*
74 * Post finished request. 74 * Post finished request.
75 */ 75 */
76static inline void 76static void
77tapeblock_end_request(struct request *req, int uptodate) 77tapeblock_end_request(struct request *req, int uptodate)
78{ 78{
79 if (end_that_request_first(req, uptodate, req->hard_nr_sectors)) 79 if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
@@ -108,7 +108,7 @@ __tapeblock_end_request(struct tape_request *ccw_req, void *data)
108/* 108/*
109 * Feed the tape device CCW queue with requests supplied in a list. 109 * Feed the tape device CCW queue with requests supplied in a list.
110 */ 110 */
111static inline int 111static int
112tapeblock_start_request(struct tape_device *device, struct request *req) 112tapeblock_start_request(struct tape_device *device, struct request *req)
113{ 113{
114 struct tape_request * ccw_req; 114 struct tape_request * ccw_req;
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 31198c8f2718..9faea04e11e9 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -3,7 +3,7 @@
3 * character device frontend for tape device driver 3 * character device frontend for tape device driver
4 * 4 *
5 * S390 and zSeries version 5 * S390 and zSeries version
6 * Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Copyright IBM Corp. 2001,2006
7 * Author(s): Carsten Otte <cotte@de.ibm.com> 7 * Author(s): Carsten Otte <cotte@de.ibm.com>
8 * Michael Holzheu <holzheu@de.ibm.com> 8 * Michael Holzheu <holzheu@de.ibm.com>
9 * Tuan Ngo-Anh <ngoanh@de.ibm.com> 9 * Tuan Ngo-Anh <ngoanh@de.ibm.com>
@@ -89,22 +89,7 @@ tapechar_cleanup_device(struct tape_device *device)
89 device->nt = NULL; 89 device->nt = NULL;
90} 90}
91 91
92/* 92static int
93 * Terminate write command (we write two TMs and skip backward over last)
94 * This ensures that the tape is always correctly terminated.
95 * When the user writes afterwards a new file, he will overwrite the
96 * second TM and therefore one TM will remain to separate the
97 * two files on the tape...
98 */
99static inline void
100tapechar_terminate_write(struct tape_device *device)
101{
102 if (tape_mtop(device, MTWEOF, 1) == 0 &&
103 tape_mtop(device, MTWEOF, 1) == 0)
104 tape_mtop(device, MTBSR, 1);
105}
106
107static inline int
108tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) 93tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
109{ 94{
110 struct idal_buffer *new; 95 struct idal_buffer *new;
@@ -137,7 +122,7 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
137/* 122/*
138 * Tape device read function 123 * Tape device read function
139 */ 124 */
140ssize_t 125static ssize_t
141tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) 126tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
142{ 127{
143 struct tape_device *device; 128 struct tape_device *device;
@@ -201,7 +186,7 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
201/* 186/*
202 * Tape device write function 187 * Tape device write function
203 */ 188 */
204ssize_t 189static ssize_t
205tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos) 190tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos)
206{ 191{
207 struct tape_device *device; 192 struct tape_device *device;
@@ -291,7 +276,7 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t
291/* 276/*
292 * Character frontend tape device open function. 277 * Character frontend tape device open function.
293 */ 278 */
294int 279static int
295tapechar_open (struct inode *inode, struct file *filp) 280tapechar_open (struct inode *inode, struct file *filp)
296{ 281{
297 struct tape_device *device; 282 struct tape_device *device;
@@ -326,7 +311,7 @@ tapechar_open (struct inode *inode, struct file *filp)
326 * Character frontend tape device release function. 311 * Character frontend tape device release function.
327 */ 312 */
328 313
329int 314static int
330tapechar_release(struct inode *inode, struct file *filp) 315tapechar_release(struct inode *inode, struct file *filp)
331{ 316{
332 struct tape_device *device; 317 struct tape_device *device;
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index c6c2e918b990..e2a8a1a04bab 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -3,7 +3,7 @@
3 * basic function of the tape device driver 3 * basic function of the tape device driver
4 * 4 *
5 * S390 and zSeries version 5 * S390 and zSeries version
6 * Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Copyright IBM Corp. 2001,2006
7 * Author(s): Carsten Otte <cotte@de.ibm.com> 7 * Author(s): Carsten Otte <cotte@de.ibm.com>
8 * Michael Holzheu <holzheu@de.ibm.com> 8 * Michael Holzheu <holzheu@de.ibm.com>
9 * Tuan Ngo-Anh <ngoanh@de.ibm.com> 9 * Tuan Ngo-Anh <ngoanh@de.ibm.com>
@@ -26,9 +26,11 @@
26#include "tape_std.h" 26#include "tape_std.h"
27 27
28#define PRINTK_HEADER "TAPE_CORE: " 28#define PRINTK_HEADER "TAPE_CORE: "
29#define LONG_BUSY_TIMEOUT 180 /* seconds */
29 30
30static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *); 31static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *);
31static void tape_delayed_next_request(struct work_struct *); 32static void tape_delayed_next_request(struct work_struct *);
33static void tape_long_busy_timeout(unsigned long data);
32 34
33/* 35/*
34 * One list to contain all tape devices of all disciplines, so 36 * One list to contain all tape devices of all disciplines, so
@@ -69,10 +71,12 @@ const char *tape_op_verbose[TO_SIZE] =
69 [TO_LOAD] = "LOA", [TO_READ_CONFIG] = "RCF", 71 [TO_LOAD] = "LOA", [TO_READ_CONFIG] = "RCF",
70 [TO_READ_ATTMSG] = "RAT", 72 [TO_READ_ATTMSG] = "RAT",
71 [TO_DIS] = "DIS", [TO_ASSIGN] = "ASS", 73 [TO_DIS] = "DIS", [TO_ASSIGN] = "ASS",
72 [TO_UNASSIGN] = "UAS" 74 [TO_UNASSIGN] = "UAS", [TO_CRYPT_ON] = "CON",
75 [TO_CRYPT_OFF] = "COF", [TO_KEKL_SET] = "KLS",
76 [TO_KEKL_QUERY] = "KLQ",
73}; 77};
74 78
75static inline int 79static int
76busid_to_int(char *bus_id) 80busid_to_int(char *bus_id)
77{ 81{
78 int dec; 82 int dec;
@@ -252,7 +256,7 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate)
252/* 256/*
253 * Stop running ccw. Has to be called with the device lock held. 257 * Stop running ccw. Has to be called with the device lock held.
254 */ 258 */
255static inline int 259static int
256__tape_cancel_io(struct tape_device *device, struct tape_request *request) 260__tape_cancel_io(struct tape_device *device, struct tape_request *request)
257{ 261{
258 int retries; 262 int retries;
@@ -346,6 +350,9 @@ tape_generic_online(struct tape_device *device,
346 return -EINVAL; 350 return -EINVAL;
347 } 351 }
348 352
353 init_timer(&device->lb_timeout);
354 device->lb_timeout.function = tape_long_busy_timeout;
355
349 /* Let the discipline have a go at the device. */ 356 /* Let the discipline have a go at the device. */
350 device->discipline = discipline; 357 device->discipline = discipline;
351 if (!try_module_get(discipline->owner)) { 358 if (!try_module_get(discipline->owner)) {
@@ -385,7 +392,7 @@ out:
385 return rc; 392 return rc;
386} 393}
387 394
388static inline void 395static void
389tape_cleanup_device(struct tape_device *device) 396tape_cleanup_device(struct tape_device *device)
390{ 397{
391 tapeblock_cleanup_device(device); 398 tapeblock_cleanup_device(device);
@@ -563,7 +570,7 @@ tape_generic_probe(struct ccw_device *cdev)
563 return ret; 570 return ret;
564} 571}
565 572
566static inline void 573static void
567__tape_discard_requests(struct tape_device *device) 574__tape_discard_requests(struct tape_device *device)
568{ 575{
569 struct tape_request * request; 576 struct tape_request * request;
@@ -703,7 +710,7 @@ tape_free_request (struct tape_request * request)
703 kfree(request); 710 kfree(request);
704} 711}
705 712
706static inline int 713static int
707__tape_start_io(struct tape_device *device, struct tape_request *request) 714__tape_start_io(struct tape_device *device, struct tape_request *request)
708{ 715{
709 int rc; 716 int rc;
@@ -733,7 +740,7 @@ __tape_start_io(struct tape_device *device, struct tape_request *request)
733 return rc; 740 return rc;
734} 741}
735 742
736static inline void 743static void
737__tape_start_next_request(struct tape_device *device) 744__tape_start_next_request(struct tape_device *device)
738{ 745{
739 struct list_head *l, *n; 746 struct list_head *l, *n;
@@ -801,7 +808,23 @@ tape_delayed_next_request(struct work_struct *work)
801 spin_unlock_irq(get_ccwdev_lock(device->cdev)); 808 spin_unlock_irq(get_ccwdev_lock(device->cdev));
802} 809}
803 810
804static inline void 811static void tape_long_busy_timeout(unsigned long data)
812{
813 struct tape_request *request;
814 struct tape_device *device;
815
816 device = (struct tape_device *) data;
817 spin_lock_irq(get_ccwdev_lock(device->cdev));
818 request = list_entry(device->req_queue.next, struct tape_request, list);
819 if (request->status != TAPE_REQUEST_LONG_BUSY)
820 BUG();
821 DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id);
822 __tape_start_next_request(device);
823 device->lb_timeout.data = (unsigned long) tape_put_device(device);
824 spin_unlock_irq(get_ccwdev_lock(device->cdev));
825}
826
827static void
805__tape_end_request( 828__tape_end_request(
806 struct tape_device * device, 829 struct tape_device * device,
807 struct tape_request * request, 830 struct tape_request * request,
@@ -878,7 +901,7 @@ tape_dump_sense_dbf(struct tape_device *device, struct tape_request *request,
878 * and starts it if the tape is idle. Has to be called with 901 * and starts it if the tape is idle. Has to be called with
879 * the device lock held. 902 * the device lock held.
880 */ 903 */
881static inline int 904static int
882__tape_start_request(struct tape_device *device, struct tape_request *request) 905__tape_start_request(struct tape_device *device, struct tape_request *request)
883{ 906{
884 int rc; 907 int rc;
@@ -1094,7 +1117,22 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
1094 /* May be an unsolicited irq */ 1117 /* May be an unsolicited irq */
1095 if(request != NULL) 1118 if(request != NULL)
1096 request->rescnt = irb->scsw.count; 1119 request->rescnt = irb->scsw.count;
1097 1120 else if ((irb->scsw.dstat == 0x85 || irb->scsw.dstat == 0x80) &&
1121 !list_empty(&device->req_queue)) {
1122 /* Not Ready to Ready after long busy ? */
1123 struct tape_request *req;
1124 req = list_entry(device->req_queue.next,
1125 struct tape_request, list);
1126 if (req->status == TAPE_REQUEST_LONG_BUSY) {
1127 DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id);
1128 if (del_timer(&device->lb_timeout)) {
1129 device->lb_timeout.data = (unsigned long)
1130 tape_put_device(device);
1131 __tape_start_next_request(device);
1132 }
1133 return;
1134 }
1135 }
1098 if (irb->scsw.dstat != 0x0c) { 1136 if (irb->scsw.dstat != 0x0c) {
1099 /* Set the 'ONLINE' flag depending on sense byte 1 */ 1137 /* Set the 'ONLINE' flag depending on sense byte 1 */
1100 if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE) 1138 if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE)
@@ -1142,6 +1180,15 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
1142 break; 1180 break;
1143 case TAPE_IO_PENDING: 1181 case TAPE_IO_PENDING:
1144 break; 1182 break;
1183 case TAPE_IO_LONG_BUSY:
1184 device->lb_timeout.data =
1185 (unsigned long)tape_get_device_reference(device);
1186 device->lb_timeout.expires = jiffies +
1187 LONG_BUSY_TIMEOUT * HZ;
1188 DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id);
1189 add_timer(&device->lb_timeout);
1190 request->status = TAPE_REQUEST_LONG_BUSY;
1191 break;
1145 case TAPE_IO_RETRY: 1192 case TAPE_IO_RETRY:
1146 rc = __tape_start_io(device, request); 1193 rc = __tape_start_io(device, request);
1147 if (rc) 1194 if (rc)
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 09844621edc0..bc33068b9ce2 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -36,7 +36,7 @@
36struct tty_driver *tty3270_driver; 36struct tty_driver *tty3270_driver;
37static int tty3270_max_index; 37static int tty3270_max_index;
38 38
39struct raw3270_fn tty3270_fn; 39static struct raw3270_fn tty3270_fn;
40 40
41struct tty3270_cell { 41struct tty3270_cell {
42 unsigned char character; 42 unsigned char character;
@@ -119,8 +119,7 @@ static void tty3270_update(struct tty3270 *);
119/* 119/*
120 * Setup timeout for a device. On timeout trigger an update. 120 * Setup timeout for a device. On timeout trigger an update.
121 */ 121 */
122void 122static void tty3270_set_timer(struct tty3270 *tp, int expires)
123tty3270_set_timer(struct tty3270 *tp, int expires)
124{ 123{
125 if (expires == 0) { 124 if (expires == 0) {
126 if (timer_pending(&tp->timer) && del_timer(&tp->timer)) 125 if (timer_pending(&tp->timer) && del_timer(&tp->timer))
@@ -841,7 +840,7 @@ tty3270_del_views(void)
841 } 840 }
842} 841}
843 842
844struct raw3270_fn tty3270_fn = { 843static struct raw3270_fn tty3270_fn = {
845 .activate = tty3270_activate, 844 .activate = tty3270_activate,
846 .deactivate = tty3270_deactivate, 845 .deactivate = tty3270_deactivate,
847 .intv = (void *) tty3270_irq, 846 .intv = (void *) tty3270_irq,
@@ -1754,8 +1753,7 @@ static const struct tty_operations tty3270_ops = {
1754 .set_termios = tty3270_set_termios 1753 .set_termios = tty3270_set_termios
1755}; 1754};
1756 1755
1757void 1756static void tty3270_notifier(int index, int active)
1758tty3270_notifier(int index, int active)
1759{ 1757{
1760 if (active) 1758 if (active)
1761 tty_register_device(tty3270_driver, index, NULL); 1759 tty_register_device(tty3270_driver, index, NULL);
@@ -1767,8 +1765,7 @@ tty3270_notifier(int index, int active)
1767 * 3270 tty registration code called from tty_init(). 1765 * 3270 tty registration code called from tty_init().
1768 * Most kernel services (incl. kmalloc) are available at this poimt. 1766 * Most kernel services (incl. kmalloc) are available at this poimt.
1769 */ 1767 */
1770int __init 1768static int __init tty3270_init(void)
1771tty3270_init(void)
1772{ 1769{
1773 struct tty_driver *driver; 1770 struct tty_driver *driver;
1774 int ret; 1771 int ret;
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 6cb23040954b..8432a76b961e 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -3,7 +3,7 @@
3 * character device driver for reading z/VM system service records 3 * character device driver for reading z/VM system service records
4 * 4 *
5 * 5 *
6 * Copyright (C) 2004 IBM Corporation 6 * Copyright 2004 IBM Corporation
7 * character device driver for reading z/VM system service records, 7 * character device driver for reading z/VM system service records,
8 * Version 1.0 8 * Version 1.0
9 * Author(s): Xenia Tkatschow <xenia@us.ibm.com> 9 * Author(s): Xenia Tkatschow <xenia@us.ibm.com>
@@ -21,7 +21,7 @@
21#include <asm/cpcmd.h> 21#include <asm/cpcmd.h>
22#include <asm/debug.h> 22#include <asm/debug.h>
23#include <asm/ebcdic.h> 23#include <asm/ebcdic.h>
24#include "../net/iucv.h" 24#include <net/iucv/iucv.h>
25#include <linux/kmod.h> 25#include <linux/kmod.h>
26#include <linux/cdev.h> 26#include <linux/cdev.h>
27#include <linux/device.h> 27#include <linux/device.h>
@@ -60,12 +60,11 @@ struct vmlogrdr_priv_t {
60 char system_service[8]; 60 char system_service[8];
61 char internal_name[8]; 61 char internal_name[8];
62 char recording_name[8]; 62 char recording_name[8];
63 u16 pathid; 63 struct iucv_path *path;
64 int connection_established; 64 int connection_established;
65 int iucv_path_severed; 65 int iucv_path_severed;
66 iucv_MessagePending local_interrupt_buffer; 66 struct iucv_message local_interrupt_buffer;
67 atomic_t receive_ready; 67 atomic_t receive_ready;
68 iucv_handle_t iucv_handle;
69 int minor_num; 68 int minor_num;
70 char * buffer; 69 char * buffer;
71 char * current_position; 70 char * current_position;
@@ -97,40 +96,21 @@ static struct file_operations vmlogrdr_fops = {
97}; 96};
98 97
99 98
100static u8 iucvMagic[16] = { 99static void vmlogrdr_iucv_path_complete(struct iucv_path *, u8 ipuser[16]);
101 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 100static void vmlogrdr_iucv_path_severed(struct iucv_path *, u8 ipuser[16]);
102 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 101static void vmlogrdr_iucv_message_pending(struct iucv_path *,
103}; 102 struct iucv_message *);
104 103
105 104
106static u8 mask[] = { 105static struct iucv_handler vmlogrdr_iucv_handler = {
107 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 106 .path_complete = vmlogrdr_iucv_path_complete,
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 107 .path_severed = vmlogrdr_iucv_path_severed,
109 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 108 .message_pending = vmlogrdr_iucv_message_pending,
110 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
111}; 109};
112 110
113 111
114static u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 112static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
115 113static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
116
117static void
118vmlogrdr_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data);
119static void
120vmlogrdr_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data);
121static void
122vmlogrdr_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data);
123
124
125static iucv_interrupt_ops_t vmlogrdr_iucvops = {
126 .ConnectionComplete = vmlogrdr_iucv_ConnectionComplete,
127 .ConnectionSevered = vmlogrdr_iucv_ConnectionSevered,
128 .MessagePending = vmlogrdr_iucv_MessagePending,
129};
130
131
132DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
133DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
134 114
135/* 115/*
136 * pointer to system service private structure 116 * pointer to system service private structure
@@ -177,28 +157,29 @@ static struct cdev *vmlogrdr_cdev = NULL;
177static int recording_class_AB; 157static int recording_class_AB;
178 158
179 159
180static void 160static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
181vmlogrdr_iucv_ConnectionComplete (iucv_ConnectionComplete * eib,
182 void * pgm_data)
183{ 161{
184 struct vmlogrdr_priv_t * logptr = pgm_data; 162 struct vmlogrdr_priv_t * logptr = path->private;
163
185 spin_lock(&logptr->priv_lock); 164 spin_lock(&logptr->priv_lock);
186 logptr->connection_established = 1; 165 logptr->connection_established = 1;
187 spin_unlock(&logptr->priv_lock); 166 spin_unlock(&logptr->priv_lock);
188 wake_up(&conn_wait_queue); 167 wake_up(&conn_wait_queue);
189 return;
190} 168}
191 169
192 170
193static void 171static void vmlogrdr_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
194vmlogrdr_iucv_ConnectionSevered (iucv_ConnectionSevered * eib, void * pgm_data)
195{ 172{
196 u8 reason = (u8) eib->ipuser[8]; 173 struct vmlogrdr_priv_t * logptr = path->private;
197 struct vmlogrdr_priv_t * logptr = pgm_data; 174 u8 reason = (u8) ipuser[8];
198 175
199 printk (KERN_ERR "vmlogrdr: connection severed with" 176 printk (KERN_ERR "vmlogrdr: connection severed with"
200 " reason %i\n", reason); 177 " reason %i\n", reason);
201 178
179 iucv_path_sever(path, NULL);
180 kfree(path);
181 logptr->path = NULL;
182
202 spin_lock(&logptr->priv_lock); 183 spin_lock(&logptr->priv_lock);
203 logptr->connection_established = 0; 184 logptr->connection_established = 0;
204 logptr->iucv_path_severed = 1; 185 logptr->iucv_path_severed = 1;
@@ -210,10 +191,10 @@ vmlogrdr_iucv_ConnectionSevered (iucv_ConnectionSevered * eib, void * pgm_data)
210} 191}
211 192
212 193
213static void 194static void vmlogrdr_iucv_message_pending(struct iucv_path *path,
214vmlogrdr_iucv_MessagePending (iucv_MessagePending * eib, void * pgm_data) 195 struct iucv_message *msg)
215{ 196{
216 struct vmlogrdr_priv_t * logptr = pgm_data; 197 struct vmlogrdr_priv_t * logptr = path->private;
217 198
218 /* 199 /*
219 * This function is the bottom half so it should be quick. 200 * This function is the bottom half so it should be quick.
@@ -221,15 +202,15 @@ vmlogrdr_iucv_MessagePending (iucv_MessagePending * eib, void * pgm_data)
221 * the usage count 202 * the usage count
222 */ 203 */
223 spin_lock(&logptr->priv_lock); 204 spin_lock(&logptr->priv_lock);
224 memcpy(&(logptr->local_interrupt_buffer), eib, sizeof(*eib)); 205 memcpy(&logptr->local_interrupt_buffer, msg, sizeof(*msg));
225 atomic_inc(&logptr->receive_ready); 206 atomic_inc(&logptr->receive_ready);
226 spin_unlock(&logptr->priv_lock); 207 spin_unlock(&logptr->priv_lock);
227 wake_up_interruptible(&read_wait_queue); 208 wake_up_interruptible(&read_wait_queue);
228} 209}
229 210
230 211
231static int 212static int vmlogrdr_get_recording_class_AB(void)
232vmlogrdr_get_recording_class_AB(void) { 213{
233 char cp_command[]="QUERY COMMAND RECORDING "; 214 char cp_command[]="QUERY COMMAND RECORDING ";
234 char cp_response[80]; 215 char cp_response[80];
235 char *tail; 216 char *tail;
@@ -259,8 +240,9 @@ vmlogrdr_get_recording_class_AB(void) {
259} 240}
260 241
261 242
262static int 243static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr,
263vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) { 244 int action, int purge)
245{
264 246
265 char cp_command[80]; 247 char cp_command[80];
266 char cp_response[160]; 248 char cp_response[160];
@@ -318,8 +300,7 @@ vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
318} 300}
319 301
320 302
321static int 303static int vmlogrdr_open (struct inode *inode, struct file *filp)
322vmlogrdr_open (struct inode *inode, struct file *filp)
323{ 304{
324 int dev_num = 0; 305 int dev_num = 0;
325 struct vmlogrdr_priv_t * logptr = NULL; 306 struct vmlogrdr_priv_t * logptr = NULL;
@@ -329,10 +310,7 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
329 dev_num = iminor(inode); 310 dev_num = iminor(inode);
330 if (dev_num > MAXMINOR) 311 if (dev_num > MAXMINOR)
331 return -ENODEV; 312 return -ENODEV;
332
333 logptr = &sys_ser[dev_num]; 313 logptr = &sys_ser[dev_num];
334 if (logptr == NULL)
335 return -ENODEV;
336 314
337 /* 315 /*
338 * only allow for blocking reads to be open 316 * only allow for blocking reads to be open
@@ -345,52 +323,38 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
345 if (logptr->dev_in_use) { 323 if (logptr->dev_in_use) {
346 spin_unlock_bh(&logptr->priv_lock); 324 spin_unlock_bh(&logptr->priv_lock);
347 return -EBUSY; 325 return -EBUSY;
348 } else {
349 logptr->dev_in_use = 1;
350 spin_unlock_bh(&logptr->priv_lock);
351 } 326 }
352 327 logptr->dev_in_use = 1;
328 logptr->connection_established = 0;
329 logptr->iucv_path_severed = 0;
353 atomic_set(&logptr->receive_ready, 0); 330 atomic_set(&logptr->receive_ready, 0);
354 logptr->buffer_free = 1; 331 logptr->buffer_free = 1;
332 spin_unlock_bh(&logptr->priv_lock);
355 333
356 /* set the file options */ 334 /* set the file options */
357 filp->private_data = logptr; 335 filp->private_data = logptr;
358 filp->f_op = &vmlogrdr_fops; 336 filp->f_op = &vmlogrdr_fops;
359 337
360 /* start recording for this service*/ 338 /* start recording for this service*/
361 ret=0; 339 if (logptr->autorecording) {
362 if (logptr->autorecording)
363 ret = vmlogrdr_recording(logptr,1,logptr->autopurge); 340 ret = vmlogrdr_recording(logptr,1,logptr->autopurge);
364 if (ret) 341 if (ret)
365 printk (KERN_WARNING "vmlogrdr: failed to start " 342 printk (KERN_WARNING "vmlogrdr: failed to start "
366 "recording automatically\n"); 343 "recording automatically\n");
367
368 /* Register with iucv driver */
369 logptr->iucv_handle = iucv_register_program(iucvMagic,
370 logptr->system_service, mask, &vmlogrdr_iucvops,
371 logptr);
372
373 if (logptr->iucv_handle == NULL) {
374 printk (KERN_ERR "vmlogrdr: failed to register with"
375 "iucv driver\n");
376 goto not_registered;
377 } 344 }
378 345
379 /* create connection to the system service */ 346 /* create connection to the system service */
380 spin_lock_bh(&logptr->priv_lock); 347 logptr->path = iucv_path_alloc(10, 0, GFP_KERNEL);
381 logptr->connection_established = 0; 348 if (!logptr->path)
382 logptr->iucv_path_severed = 0; 349 goto out_dev;
383 spin_unlock_bh(&logptr->priv_lock); 350 connect_rc = iucv_path_connect(logptr->path, &vmlogrdr_iucv_handler,
384 351 logptr->system_service, NULL, NULL,
385 connect_rc = iucv_connect (&(logptr->pathid), 10, iucvMagic, 352 logptr);
386 logptr->system_service, iucv_host, 0,
387 NULL, NULL,
388 logptr->iucv_handle, NULL);
389 if (connect_rc) { 353 if (connect_rc) {
390 printk (KERN_ERR "vmlogrdr: iucv connection to %s " 354 printk (KERN_ERR "vmlogrdr: iucv connection to %s "
391 "failed with rc %i \n", logptr->system_service, 355 "failed with rc %i \n", logptr->system_service,
392 connect_rc); 356 connect_rc);
393 goto not_connected; 357 goto out_path;
394 } 358 }
395 359
396 /* We've issued the connect and now we must wait for a 360 /* We've issued the connect and now we must wait for a
@@ -399,35 +363,28 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
399 */ 363 */
400 wait_event(conn_wait_queue, (logptr->connection_established) 364 wait_event(conn_wait_queue, (logptr->connection_established)
401 || (logptr->iucv_path_severed)); 365 || (logptr->iucv_path_severed));
402 if (logptr->iucv_path_severed) { 366 if (logptr->iucv_path_severed)
403 goto not_connected; 367 goto out_record;
404 }
405
406 return nonseekable_open(inode, filp); 368 return nonseekable_open(inode, filp);
407 369
408not_connected: 370out_record:
409 iucv_unregister_program(logptr->iucv_handle);
410 logptr->iucv_handle = NULL;
411not_registered:
412 if (logptr->autorecording) 371 if (logptr->autorecording)
413 vmlogrdr_recording(logptr,0,logptr->autopurge); 372 vmlogrdr_recording(logptr,0,logptr->autopurge);
373out_path:
374 kfree(logptr->path); /* kfree(NULL) is ok. */
375 logptr->path = NULL;
376out_dev:
414 logptr->dev_in_use = 0; 377 logptr->dev_in_use = 0;
415 return -EIO; 378 return -EIO;
416
417
418} 379}
419 380
420 381
421static int 382static int vmlogrdr_release (struct inode *inode, struct file *filp)
422vmlogrdr_release (struct inode *inode, struct file *filp)
423{ 383{
424 int ret; 384 int ret;
425 385
426 struct vmlogrdr_priv_t * logptr = filp->private_data; 386 struct vmlogrdr_priv_t * logptr = filp->private_data;
427 387
428 iucv_unregister_program(logptr->iucv_handle);
429 logptr->iucv_handle = NULL;
430
431 if (logptr->autorecording) { 388 if (logptr->autorecording) {
432 ret = vmlogrdr_recording(logptr,0,logptr->autopurge); 389 ret = vmlogrdr_recording(logptr,0,logptr->autopurge);
433 if (ret) 390 if (ret)
@@ -440,8 +397,8 @@ vmlogrdr_release (struct inode *inode, struct file *filp)
440} 397}
441 398
442 399
443static int 400static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv)
444vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) { 401{
445 int rc, *temp; 402 int rc, *temp;
446 /* we need to keep track of two data sizes here: 403 /* we need to keep track of two data sizes here:
447 * The number of bytes we need to receive from iucv and 404 * The number of bytes we need to receive from iucv and
@@ -462,8 +419,7 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
462 * We need to return the total length of the record 419 * We need to return the total length of the record
463 * + size of FENCE in the first 4 bytes of the buffer. 420 * + size of FENCE in the first 4 bytes of the buffer.
464 */ 421 */
465 iucv_data_count = 422 iucv_data_count = priv->local_interrupt_buffer.length;
466 priv->local_interrupt_buffer.ln1msg2.ipbfln1f;
467 user_data_count = sizeof(int); 423 user_data_count = sizeof(int);
468 temp = (int*)priv->buffer; 424 temp = (int*)priv->buffer;
469 *temp= iucv_data_count + sizeof(FENCE); 425 *temp= iucv_data_count + sizeof(FENCE);
@@ -475,14 +431,10 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
475 */ 431 */
476 if (iucv_data_count > NET_BUFFER_SIZE) 432 if (iucv_data_count > NET_BUFFER_SIZE)
477 iucv_data_count = NET_BUFFER_SIZE; 433 iucv_data_count = NET_BUFFER_SIZE;
478 rc = iucv_receive(priv->pathid, 434 rc = iucv_message_receive(priv->path,
479 priv->local_interrupt_buffer.ipmsgid, 435 &priv->local_interrupt_buffer,
480 priv->local_interrupt_buffer.iptrgcls, 436 0, buffer, iucv_data_count,
481 buffer, 437 &priv->residual_length);
482 iucv_data_count,
483 NULL,
484 NULL,
485 &priv->residual_length);
486 spin_unlock_bh(&priv->priv_lock); 438 spin_unlock_bh(&priv->priv_lock);
487 /* An rc of 5 indicates that the record was bigger then 439 /* An rc of 5 indicates that the record was bigger then
488 * the buffer, which is OK for us. A 9 indicates that the 440 * the buffer, which is OK for us. A 9 indicates that the
@@ -514,8 +466,8 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
514} 466}
515 467
516 468
517static ssize_t 469static ssize_t vmlogrdr_read(struct file *filp, char __user *data,
518vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos) 470 size_t count, loff_t * ppos)
519{ 471{
520 int rc; 472 int rc;
521 struct vmlogrdr_priv_t * priv = filp->private_data; 473 struct vmlogrdr_priv_t * priv = filp->private_data;
@@ -547,8 +499,10 @@ vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos)
547 return count; 499 return count;
548} 500}
549 501
550static ssize_t 502static ssize_t vmlogrdr_autopurge_store(struct device * dev,
551vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) { 503 struct device_attribute *attr,
504 const char * buf, size_t count)
505{
552 struct vmlogrdr_priv_t *priv = dev->driver_data; 506 struct vmlogrdr_priv_t *priv = dev->driver_data;
553 ssize_t ret = count; 507 ssize_t ret = count;
554 508
@@ -566,8 +520,10 @@ vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, con
566} 520}
567 521
568 522
569static ssize_t 523static ssize_t vmlogrdr_autopurge_show(struct device *dev,
570vmlogrdr_autopurge_show(struct device *dev, struct device_attribute *attr, char *buf) { 524 struct device_attribute *attr,
525 char *buf)
526{
571 struct vmlogrdr_priv_t *priv = dev->driver_data; 527 struct vmlogrdr_priv_t *priv = dev->driver_data;
572 return sprintf(buf, "%u\n", priv->autopurge); 528 return sprintf(buf, "%u\n", priv->autopurge);
573} 529}
@@ -577,8 +533,10 @@ static DEVICE_ATTR(autopurge, 0644, vmlogrdr_autopurge_show,
577 vmlogrdr_autopurge_store); 533 vmlogrdr_autopurge_store);
578 534
579 535
580static ssize_t 536static ssize_t vmlogrdr_purge_store(struct device * dev,
581vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) { 537 struct device_attribute *attr,
538 const char * buf, size_t count)
539{
582 540
583 char cp_command[80]; 541 char cp_command[80];
584 char cp_response[80]; 542 char cp_response[80];
@@ -618,9 +576,10 @@ vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const c
618static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store); 576static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store);
619 577
620 578
621static ssize_t 579static ssize_t vmlogrdr_autorecording_store(struct device *dev,
622vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr, const char *buf, 580 struct device_attribute *attr,
623 size_t count) { 581 const char *buf, size_t count)
582{
624 struct vmlogrdr_priv_t *priv = dev->driver_data; 583 struct vmlogrdr_priv_t *priv = dev->driver_data;
625 ssize_t ret = count; 584 ssize_t ret = count;
626 585
@@ -638,8 +597,10 @@ vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr,
638} 597}
639 598
640 599
641static ssize_t 600static ssize_t vmlogrdr_autorecording_show(struct device *dev,
642vmlogrdr_autorecording_show(struct device *dev, struct device_attribute *attr, char *buf) { 601 struct device_attribute *attr,
602 char *buf)
603{
643 struct vmlogrdr_priv_t *priv = dev->driver_data; 604 struct vmlogrdr_priv_t *priv = dev->driver_data;
644 return sprintf(buf, "%u\n", priv->autorecording); 605 return sprintf(buf, "%u\n", priv->autorecording);
645} 606}
@@ -649,9 +610,10 @@ static DEVICE_ATTR(autorecording, 0644, vmlogrdr_autorecording_show,
649 vmlogrdr_autorecording_store); 610 vmlogrdr_autorecording_store);
650 611
651 612
652static ssize_t 613static ssize_t vmlogrdr_recording_store(struct device * dev,
653vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) { 614 struct device_attribute *attr,
654 615 const char * buf, size_t count)
616{
655 struct vmlogrdr_priv_t *priv = dev->driver_data; 617 struct vmlogrdr_priv_t *priv = dev->driver_data;
656 ssize_t ret; 618 ssize_t ret;
657 619
@@ -676,8 +638,9 @@ vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, con
676static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store); 638static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store);
677 639
678 640
679static ssize_t 641static ssize_t vmlogrdr_recording_status_show(struct device_driver *driver,
680vmlogrdr_recording_status_show(struct device_driver *driver, char *buf) { 642 char *buf)
643{
681 644
682 char cp_command[] = "QUERY RECORDING "; 645 char cp_command[] = "QUERY RECORDING ";
683 int len; 646 int len;
@@ -710,52 +673,63 @@ static struct device_driver vmlogrdr_driver = {
710}; 673};
711 674
712 675
713static int 676static int vmlogrdr_register_driver(void)
714vmlogrdr_register_driver(void) { 677{
715 int ret; 678 int ret;
716 679
680 /* Register with iucv driver */
681 ret = iucv_register(&vmlogrdr_iucv_handler, 1);
682 if (ret) {
683 printk (KERN_ERR "vmlogrdr: failed to register with"
684 "iucv driver\n");
685 goto out;
686 }
687
717 ret = driver_register(&vmlogrdr_driver); 688 ret = driver_register(&vmlogrdr_driver);
718 if (ret) { 689 if (ret) {
719 printk(KERN_ERR "vmlogrdr: failed to register driver.\n"); 690 printk(KERN_ERR "vmlogrdr: failed to register driver.\n");
720 return ret; 691 goto out_iucv;
721 } 692 }
722 693
723 ret = driver_create_file(&vmlogrdr_driver, 694 ret = driver_create_file(&vmlogrdr_driver,
724 &driver_attr_recording_status); 695 &driver_attr_recording_status);
725 if (ret) { 696 if (ret) {
726 printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n"); 697 printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");
727 goto unregdriver; 698 goto out_driver;
728 } 699 }
729 700
730 vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr"); 701 vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
731 if (IS_ERR(vmlogrdr_class)) { 702 if (IS_ERR(vmlogrdr_class)) {
732 printk(KERN_ERR "vmlogrdr: failed to create class.\n"); 703 printk(KERN_ERR "vmlogrdr: failed to create class.\n");
733 ret=PTR_ERR(vmlogrdr_class); 704 ret = PTR_ERR(vmlogrdr_class);
734 vmlogrdr_class=NULL; 705 vmlogrdr_class = NULL;
735 goto unregattr; 706 goto out_attr;
736 } 707 }
737 return 0; 708 return 0;
738 709
739unregattr: 710out_attr:
740 driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status); 711 driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
741unregdriver: 712out_driver:
742 driver_unregister(&vmlogrdr_driver); 713 driver_unregister(&vmlogrdr_driver);
714out_iucv:
715 iucv_unregister(&vmlogrdr_iucv_handler, 1);
716out:
743 return ret; 717 return ret;
744} 718}
745 719
746 720
747static void 721static void vmlogrdr_unregister_driver(void)
748vmlogrdr_unregister_driver(void) { 722{
749 class_destroy(vmlogrdr_class); 723 class_destroy(vmlogrdr_class);
750 vmlogrdr_class = NULL; 724 vmlogrdr_class = NULL;
751 driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status); 725 driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
752 driver_unregister(&vmlogrdr_driver); 726 driver_unregister(&vmlogrdr_driver);
753 return; 727 iucv_unregister(&vmlogrdr_iucv_handler, 1);
754} 728}
755 729
756 730
757static int 731static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
758vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) { 732{
759 struct device *dev; 733 struct device *dev;
760 int ret; 734 int ret;
761 735
@@ -804,9 +778,10 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
804} 778}
805 779
806 780
807static int 781static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv)
808vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) { 782{
809 class_device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num)); 783 class_device_destroy(vmlogrdr_class,
784 MKDEV(vmlogrdr_major, priv->minor_num));
810 if (priv->device != NULL) { 785 if (priv->device != NULL) {
811 sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group); 786 sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
812 device_unregister(priv->device); 787 device_unregister(priv->device);
@@ -816,8 +791,8 @@ vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
816} 791}
817 792
818 793
819static int 794static int vmlogrdr_register_cdev(dev_t dev)
820vmlogrdr_register_cdev(dev_t dev) { 795{
821 int rc = 0; 796 int rc = 0;
822 vmlogrdr_cdev = cdev_alloc(); 797 vmlogrdr_cdev = cdev_alloc();
823 if (!vmlogrdr_cdev) { 798 if (!vmlogrdr_cdev) {
@@ -837,9 +812,10 @@ vmlogrdr_register_cdev(dev_t dev) {
837} 812}
838 813
839 814
840static void 815static void vmlogrdr_cleanup(void)
841vmlogrdr_cleanup(void) { 816{
842 int i; 817 int i;
818
843 if (vmlogrdr_cdev) { 819 if (vmlogrdr_cdev) {
844 cdev_del(vmlogrdr_cdev); 820 cdev_del(vmlogrdr_cdev);
845 vmlogrdr_cdev=NULL; 821 vmlogrdr_cdev=NULL;
@@ -856,8 +832,7 @@ vmlogrdr_cleanup(void) {
856} 832}
857 833
858 834
859static int 835static int vmlogrdr_init(void)
860vmlogrdr_init(void)
861{ 836{
862 int rc; 837 int rc;
863 int i; 838 int i;
@@ -907,8 +882,7 @@ cleanup:
907} 882}
908 883
909 884
910static void 885static void vmlogrdr_exit(void)
911vmlogrdr_exit(void)
912{ 886{
913 vmlogrdr_cleanup(); 887 vmlogrdr_cleanup();
914 printk (KERN_INFO "vmlogrdr: driver unloaded\n"); 888 printk (KERN_INFO "vmlogrdr: driver unloaded\n");