aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd.c8
-rw-r--r--drivers/s390/block/dasd_eckd.c16
-rw-r--r--drivers/s390/block/dasd_ioctl.c21
-rw-r--r--drivers/s390/block/dasd_proc.c7
-rw-r--r--drivers/s390/char/con3215.c17
-rw-r--r--drivers/s390/char/fs3270.c17
-rw-r--r--drivers/s390/char/sclp_vt220.c4
-rw-r--r--drivers/s390/char/tape_block.c39
-rw-r--r--drivers/s390/char/tape_char.c18
-rw-r--r--drivers/s390/char/vmcp.c12
-rw-r--r--drivers/s390/cio/Makefile2
-rw-r--r--drivers/s390/cio/chsc_sch.c23
-rw-r--r--drivers/s390/cio/qdio.h36
-rw-r--r--drivers/s390/cio/qdio_debug.c114
-rw-r--r--drivers/s390/cio/qdio_main.c75
-rw-r--r--drivers/s390/cio/qdio_perf.c149
-rw-r--r--drivers/s390/cio/qdio_perf.h62
-rw-r--r--drivers/s390/cio/qdio_thinint.c8
-rw-r--r--drivers/s390/crypto/zcrypt_api.c4
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c2
-rw-r--r--drivers/s390/net/claw.c2
-rw-r--r--drivers/s390/scsi/zfcp_cfdc.c9
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c2
-rw-r--r--drivers/s390/scsi/zfcp_ext.h5
-rw-r--r--drivers/s390/scsi/zfcp_fc.c93
-rw-r--r--drivers/s390/scsi/zfcp_fc.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c19
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c1
29 files changed, 354 insertions, 415 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index fdb2e7c14506..5905936c7c60 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1004,8 +1004,8 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
1004 if (device == NULL || 1004 if (device == NULL ||
1005 device != dasd_device_from_cdev_locked(cdev) || 1005 device != dasd_device_from_cdev_locked(cdev) ||
1006 strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { 1006 strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
1007 DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: " 1007 DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s",
1008 "bus_id %s", dev_name(&cdev->dev)); 1008 "invalid device in request");
1009 return; 1009 return;
1010 } 1010 }
1011 1011
@@ -1078,8 +1078,8 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1078 device = (struct dasd_device *) cqr->startdev; 1078 device = (struct dasd_device *) cqr->startdev;
1079 if (!device || 1079 if (!device ||
1080 strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { 1080 strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
1081 DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: " 1081 DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s",
1082 "bus_id %s", dev_name(&cdev->dev)); 1082 "invalid device in request");
1083 return; 1083 return;
1084 } 1084 }
1085 1085
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 5819dc02a143..1cca21aafaba 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -23,6 +23,7 @@
23#include <asm/debug.h> 23#include <asm/debug.h>
24#include <asm/idals.h> 24#include <asm/idals.h>
25#include <asm/ebcdic.h> 25#include <asm/ebcdic.h>
26#include <asm/compat.h>
26#include <asm/io.h> 27#include <asm/io.h>
27#include <asm/uaccess.h> 28#include <asm/uaccess.h>
28#include <asm/cio.h> 29#include <asm/cio.h>
@@ -2844,13 +2845,16 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
2844 rc = -EFAULT; 2845 rc = -EFAULT;
2845 if (copy_from_user(&usrparm, argp, sizeof(usrparm))) 2846 if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
2846 goto out; 2847 goto out;
2847#ifndef CONFIG_64BIT 2848 if (is_compat_task() || sizeof(long) == 4) {
2848 /* Make sure pointers are sane even on 31 bit. */ 2849 /* Make sure pointers are sane even on 31 bit. */
2849 if ((usrparm.psf_data >> 32) != 0 || (usrparm.rssd_result >> 32) != 0) {
2850 rc = -EINVAL; 2850 rc = -EINVAL;
2851 goto out; 2851 if ((usrparm.psf_data >> 32) != 0)
2852 goto out;
2853 if ((usrparm.rssd_result >> 32) != 0)
2854 goto out;
2855 usrparm.psf_data &= 0x7fffffffULL;
2856 usrparm.rssd_result &= 0x7fffffffULL;
2852 } 2857 }
2853#endif
2854 /* alloc I/O data area */ 2858 /* alloc I/O data area */
2855 psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA); 2859 psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA);
2856 rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA); 2860 rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA);
@@ -3029,7 +3033,7 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
3029 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 3033 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
3030 " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d\n", 3034 " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d\n",
3031 req, scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw), 3035 req, scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw),
3032 scsw_cc(&irb->scsw), req->intrc); 3036 scsw_cc(&irb->scsw), req ? req->intrc : 0);
3033 len += sprintf(page + len, KERN_ERR PRINTK_HEADER 3037 len += sprintf(page + len, KERN_ERR PRINTK_HEADER
3034 " device %s: Failing CCW: %p\n", 3038 " device %s: Failing CCW: %p\n",
3035 dev_name(&device->cdev->dev), 3039 dev_name(&device->cdev->dev),
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 478bcdb90b6f..7039d9cf0fb4 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -17,7 +17,7 @@
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/blkpg.h> 18#include <linux/blkpg.h>
19#include <linux/smp_lock.h> 19#include <linux/smp_lock.h>
20 20#include <asm/compat.h>
21#include <asm/ccwdev.h> 21#include <asm/ccwdev.h>
22#include <asm/cmb.h> 22#include <asm/cmb.h>
23#include <asm/uaccess.h> 23#include <asm/uaccess.h>
@@ -260,7 +260,7 @@ static int dasd_ioctl_information(struct dasd_block *block,
260 struct ccw_dev_id dev_id; 260 struct ccw_dev_id dev_id;
261 261
262 base = block->base; 262 base = block->base;
263 if (!base->discipline->fill_info) 263 if (!base->discipline || !base->discipline->fill_info)
264 return -EINVAL; 264 return -EINVAL;
265 265
266 dasd_info = kzalloc(sizeof(struct dasd_information2_t), GFP_KERNEL); 266 dasd_info = kzalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
@@ -303,10 +303,7 @@ static int dasd_ioctl_information(struct dasd_block *block,
303 dasd_info->features |= 303 dasd_info->features |=
304 ((base->features & DASD_FEATURE_READONLY) != 0); 304 ((base->features & DASD_FEATURE_READONLY) != 0);
305 305
306 if (base->discipline) 306 memcpy(dasd_info->type, base->discipline->name, 4);
307 memcpy(dasd_info->type, base->discipline->name, 4);
308 else
309 memcpy(dasd_info->type, "none", 4);
310 307
311 if (block->request_queue->request_fn) { 308 if (block->request_queue->request_fn) {
312 struct list_head *l; 309 struct list_head *l;
@@ -358,9 +355,8 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
358} 355}
359 356
360static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd, 357static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
361 unsigned long arg) 358 struct cmbdata __user *argp)
362{ 359{
363 struct cmbdata __user *argp = (void __user *) arg;
364 size_t size = _IOC_SIZE(cmd); 360 size_t size = _IOC_SIZE(cmd);
365 struct cmbdata data; 361 struct cmbdata data;
366 int ret; 362 int ret;
@@ -376,7 +372,12 @@ dasd_do_ioctl(struct block_device *bdev, fmode_t mode,
376 unsigned int cmd, unsigned long arg) 372 unsigned int cmd, unsigned long arg)
377{ 373{
378 struct dasd_block *block = bdev->bd_disk->private_data; 374 struct dasd_block *block = bdev->bd_disk->private_data;
379 void __user *argp = (void __user *)arg; 375 void __user *argp;
376
377 if (is_compat_task())
378 argp = compat_ptr(arg);
379 else
380 argp = (void __user *)arg;
380 381
381 if (!block) 382 if (!block)
382 return -ENODEV; 383 return -ENODEV;
@@ -414,7 +415,7 @@ dasd_do_ioctl(struct block_device *bdev, fmode_t mode,
414 case BIODASDCMFDISABLE: 415 case BIODASDCMFDISABLE:
415 return disable_cmf(block->base->cdev); 416 return disable_cmf(block->base->cdev);
416 case BIODASDREADALLCMB: 417 case BIODASDREADALLCMB:
417 return dasd_ioctl_readall_cmb(block, cmd, arg); 418 return dasd_ioctl_readall_cmb(block, cmd, argp);
418 default: 419 default:
419 /* if the discipline has an ioctl method try it. */ 420 /* if the discipline has an ioctl method try it. */
420 if (block->base->discipline->ioctl) { 421 if (block->base->discipline->ioctl) {
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 6315fbd8e68b..71f95f54866f 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -72,7 +72,7 @@ dasd_devices_show(struct seq_file *m, void *v)
72 /* Print device number. */ 72 /* Print device number. */
73 seq_printf(m, "%s", dev_name(&device->cdev->dev)); 73 seq_printf(m, "%s", dev_name(&device->cdev->dev));
74 /* Print discipline string. */ 74 /* Print discipline string. */
75 if (device != NULL && device->discipline != NULL) 75 if (device->discipline != NULL)
76 seq_printf(m, "(%s)", device->discipline->name); 76 seq_printf(m, "(%s)", device->discipline->name);
77 else 77 else
78 seq_printf(m, "(none)"); 78 seq_printf(m, "(none)");
@@ -92,10 +92,7 @@ dasd_devices_show(struct seq_file *m, void *v)
92 substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " "; 92 substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
93 seq_printf(m, "%4s: ", substr); 93 seq_printf(m, "%4s: ", substr);
94 /* Print device status information. */ 94 /* Print device status information. */
95 switch ((device != NULL) ? device->state : -1) { 95 switch (device->state) {
96 case -1:
97 seq_printf(m, "unknown");
98 break;
99 case DASD_STATE_NEW: 96 case DASD_STATE_NEW:
100 seq_printf(m, "new"); 97 seq_printf(m, "new");
101 break; 98 break;
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 9d61683b5633..59ec073724bf 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -1037,22 +1037,6 @@ static void tty3215_flush_buffer(struct tty_struct *tty)
1037} 1037}
1038 1038
1039/* 1039/*
1040 * Currently we don't have any io controls for 3215 ttys
1041 */
1042static int tty3215_ioctl(struct tty_struct *tty, struct file * file,
1043 unsigned int cmd, unsigned long arg)
1044{
1045 if (tty->flags & (1 << TTY_IO_ERROR))
1046 return -EIO;
1047
1048 switch (cmd) {
1049 default:
1050 return -ENOIOCTLCMD;
1051 }
1052 return 0;
1053}
1054
1055/*
1056 * Disable reading from a 3215 tty 1040 * Disable reading from a 3215 tty
1057 */ 1041 */
1058static void tty3215_throttle(struct tty_struct * tty) 1042static void tty3215_throttle(struct tty_struct * tty)
@@ -1117,7 +1101,6 @@ static const struct tty_operations tty3215_ops = {
1117 .write_room = tty3215_write_room, 1101 .write_room = tty3215_write_room,
1118 .chars_in_buffer = tty3215_chars_in_buffer, 1102 .chars_in_buffer = tty3215_chars_in_buffer,
1119 .flush_buffer = tty3215_flush_buffer, 1103 .flush_buffer = tty3215_flush_buffer,
1120 .ioctl = tty3215_ioctl,
1121 .throttle = tty3215_throttle, 1104 .throttle = tty3215_throttle,
1122 .unthrottle = tty3215_unthrottle, 1105 .unthrottle = tty3215_unthrottle,
1123 .stop = tty3215_stop, 1106 .stop = tty3215_stop,
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 247b2b934728..31c59b0d6df0 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -15,6 +15,7 @@
15#include <linux/types.h> 15#include <linux/types.h>
16#include <linux/smp_lock.h> 16#include <linux/smp_lock.h>
17 17
18#include <asm/compat.h>
18#include <asm/ccwdev.h> 19#include <asm/ccwdev.h>
19#include <asm/cio.h> 20#include <asm/cio.h>
20#include <asm/ebcdic.h> 21#include <asm/ebcdic.h>
@@ -322,6 +323,7 @@ fs3270_write(struct file *filp, const char __user *data, size_t count, loff_t *o
322static long 323static long
323fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 324fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
324{ 325{
326 char __user *argp;
325 struct fs3270 *fp; 327 struct fs3270 *fp;
326 struct raw3270_iocb iocb; 328 struct raw3270_iocb iocb;
327 int rc; 329 int rc;
@@ -329,6 +331,10 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
329 fp = filp->private_data; 331 fp = filp->private_data;
330 if (!fp) 332 if (!fp)
331 return -ENODEV; 333 return -ENODEV;
334 if (is_compat_task())
335 argp = compat_ptr(arg);
336 else
337 argp = (char __user *)arg;
332 rc = 0; 338 rc = 0;
333 mutex_lock(&fs3270_mutex); 339 mutex_lock(&fs3270_mutex);
334 switch (cmd) { 340 switch (cmd) {
@@ -339,10 +345,10 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
339 fp->write_command = arg; 345 fp->write_command = arg;
340 break; 346 break;
341 case TUBGETI: 347 case TUBGETI:
342 rc = put_user(fp->read_command, (char __user *) arg); 348 rc = put_user(fp->read_command, argp);
343 break; 349 break;
344 case TUBGETO: 350 case TUBGETO:
345 rc = put_user(fp->write_command,(char __user *) arg); 351 rc = put_user(fp->write_command, argp);
346 break; 352 break;
347 case TUBGETMOD: 353 case TUBGETMOD:
348 iocb.model = fp->view.model; 354 iocb.model = fp->view.model;
@@ -351,8 +357,7 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
351 iocb.pf_cnt = 24; 357 iocb.pf_cnt = 24;
352 iocb.re_cnt = 20; 358 iocb.re_cnt = 20;
353 iocb.map = 0; 359 iocb.map = 0;
354 if (copy_to_user((char __user *) arg, &iocb, 360 if (copy_to_user(argp, &iocb, sizeof(struct raw3270_iocb)))
355 sizeof(struct raw3270_iocb)))
356 rc = -EFAULT; 361 rc = -EFAULT;
357 break; 362 break;
358 } 363 }
@@ -511,8 +516,8 @@ static const struct file_operations fs3270_fops = {
511 .write = fs3270_write, /* write */ 516 .write = fs3270_write, /* write */
512 .unlocked_ioctl = fs3270_ioctl, /* ioctl */ 517 .unlocked_ioctl = fs3270_ioctl, /* ioctl */
513 .compat_ioctl = fs3270_ioctl, /* ioctl */ 518 .compat_ioctl = fs3270_ioctl, /* ioctl */
514 .open = fs3270_open, /* open */ 519 .open = fs3270_open, /* open */
515 .release = fs3270_close, /* release */ 520 .release = fs3270_close, /* release */
516}; 521};
517 522
518/* 523/*
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index b9d2a007e93b..3796ffdb8479 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -495,6 +495,10 @@ sclp_vt220_open(struct tty_struct *tty, struct file *filp)
495 if (tty->driver_data == NULL) 495 if (tty->driver_data == NULL)
496 return -ENOMEM; 496 return -ENOMEM;
497 tty->low_latency = 0; 497 tty->low_latency = 0;
498 if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
499 tty->winsize.ws_row = 24;
500 tty->winsize.ws_col = 80;
501 }
498 } 502 }
499 return 0; 503 return 0;
500} 504}
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 96816149368a..8d3d720737da 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -46,8 +46,6 @@
46 */ 46 */
47static int tapeblock_open(struct block_device *, fmode_t); 47static int tapeblock_open(struct block_device *, fmode_t);
48static int tapeblock_release(struct gendisk *, fmode_t); 48static int tapeblock_release(struct gendisk *, fmode_t);
49static int tapeblock_ioctl(struct block_device *, fmode_t, unsigned int,
50 unsigned long);
51static int tapeblock_medium_changed(struct gendisk *); 49static int tapeblock_medium_changed(struct gendisk *);
52static int tapeblock_revalidate_disk(struct gendisk *); 50static int tapeblock_revalidate_disk(struct gendisk *);
53 51
@@ -55,7 +53,6 @@ static const struct block_device_operations tapeblock_fops = {
55 .owner = THIS_MODULE, 53 .owner = THIS_MODULE,
56 .open = tapeblock_open, 54 .open = tapeblock_open,
57 .release = tapeblock_release, 55 .release = tapeblock_release,
58 .ioctl = tapeblock_ioctl,
59 .media_changed = tapeblock_medium_changed, 56 .media_changed = tapeblock_medium_changed,
60 .revalidate_disk = tapeblock_revalidate_disk, 57 .revalidate_disk = tapeblock_revalidate_disk,
61}; 58};
@@ -416,42 +413,6 @@ tapeblock_release(struct gendisk *disk, fmode_t mode)
416} 413}
417 414
418/* 415/*
419 * Support of some generic block device IOCTLs.
420 */
421static int
422tapeblock_ioctl(
423 struct block_device * bdev,
424 fmode_t mode,
425 unsigned int command,
426 unsigned long arg
427) {
428 int rc;
429 int minor;
430 struct gendisk *disk = bdev->bd_disk;
431 struct tape_device *device;
432
433 rc = 0;
434 BUG_ON(!disk);
435 device = disk->private_data;
436 BUG_ON(!device);
437 minor = MINOR(bdev->bd_dev);
438
439 DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command);
440 DBF_LH(6, "device = %d:%d\n", tapeblock_major, minor);
441
442 switch (command) {
443 /* Refuse some IOCTL calls without complaining (mount). */
444 case 0x5310: /* CDROMMULTISESSION */
445 rc = -EINVAL;
446 break;
447 default:
448 rc = -EINVAL;
449 }
450
451 return rc;
452}
453
454/*
455 * Initialize block device frontend. 416 * Initialize block device frontend.
456 */ 417 */
457int 418int
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 2125ec7d95f0..539045acaad4 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -18,6 +18,7 @@
18#include <linux/proc_fs.h> 18#include <linux/proc_fs.h>
19#include <linux/mtio.h> 19#include <linux/mtio.h>
20#include <linux/smp_lock.h> 20#include <linux/smp_lock.h>
21#include <linux/compat.h>
21 22
22#include <asm/uaccess.h> 23#include <asm/uaccess.h>
23 24
@@ -37,8 +38,9 @@ static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t
37static int tapechar_open(struct inode *,struct file *); 38static int tapechar_open(struct inode *,struct file *);
38static int tapechar_release(struct inode *,struct file *); 39static int tapechar_release(struct inode *,struct file *);
39static long tapechar_ioctl(struct file *, unsigned int, unsigned long); 40static long tapechar_ioctl(struct file *, unsigned int, unsigned long);
40static long tapechar_compat_ioctl(struct file *, unsigned int, 41#ifdef CONFIG_COMPAT
41 unsigned long); 42static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long);
43#endif
42 44
43static const struct file_operations tape_fops = 45static const struct file_operations tape_fops =
44{ 46{
@@ -46,7 +48,9 @@ static const struct file_operations tape_fops =
46 .read = tapechar_read, 48 .read = tapechar_read,
47 .write = tapechar_write, 49 .write = tapechar_write,
48 .unlocked_ioctl = tapechar_ioctl, 50 .unlocked_ioctl = tapechar_ioctl,
51#ifdef CONFIG_COMPAT
49 .compat_ioctl = tapechar_compat_ioctl, 52 .compat_ioctl = tapechar_compat_ioctl,
53#endif
50 .open = tapechar_open, 54 .open = tapechar_open,
51 .release = tapechar_release, 55 .release = tapechar_release,
52}; 56};
@@ -457,15 +461,22 @@ tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data)
457 return rc; 461 return rc;
458} 462}
459 463
464#ifdef CONFIG_COMPAT
460static long 465static long
461tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) 466tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
462{ 467{
463 struct tape_device *device = filp->private_data; 468 struct tape_device *device = filp->private_data;
464 int rval = -ENOIOCTLCMD; 469 int rval = -ENOIOCTLCMD;
470 unsigned long argp;
465 471
472 /* The 'arg' argument of any ioctl function may only be used for
473 * pointers because of the compat pointer conversion.
474 * Consider this when adding new ioctls.
475 */
476 argp = (unsigned long) compat_ptr(data);
466 if (device->discipline->ioctl_fn) { 477 if (device->discipline->ioctl_fn) {
467 mutex_lock(&device->mutex); 478 mutex_lock(&device->mutex);
468 rval = device->discipline->ioctl_fn(device, no, data); 479 rval = device->discipline->ioctl_fn(device, no, argp);
469 mutex_unlock(&device->mutex); 480 mutex_unlock(&device->mutex);
470 if (rval == -EINVAL) 481 if (rval == -EINVAL)
471 rval = -ENOIOCTLCMD; 482 rval = -ENOIOCTLCMD;
@@ -473,6 +484,7 @@ tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
473 484
474 return rval; 485 return rval;
475} 486}
487#endif /* CONFIG_COMPAT */
476 488
477/* 489/*
478 * Initialize character device frontend. 490 * Initialize character device frontend.
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index a6087cec55b4..921dcda77676 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -19,6 +19,7 @@
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <linux/miscdevice.h> 20#include <linux/miscdevice.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <asm/compat.h>
22#include <asm/cpcmd.h> 23#include <asm/cpcmd.h>
23#include <asm/debug.h> 24#include <asm/debug.h>
24#include <asm/uaccess.h> 25#include <asm/uaccess.h>
@@ -139,21 +140,26 @@ vmcp_write(struct file *file, const char __user *buff, size_t count,
139static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 140static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
140{ 141{
141 struct vmcp_session *session; 142 struct vmcp_session *session;
143 int __user *argp;
142 int temp; 144 int temp;
143 145
144 session = (struct vmcp_session *)file->private_data; 146 session = (struct vmcp_session *)file->private_data;
147 if (is_compat_task())
148 argp = compat_ptr(arg);
149 else
150 argp = (int __user *)arg;
145 if (mutex_lock_interruptible(&session->mutex)) 151 if (mutex_lock_interruptible(&session->mutex))
146 return -ERESTARTSYS; 152 return -ERESTARTSYS;
147 switch (cmd) { 153 switch (cmd) {
148 case VMCP_GETCODE: 154 case VMCP_GETCODE:
149 temp = session->resp_code; 155 temp = session->resp_code;
150 mutex_unlock(&session->mutex); 156 mutex_unlock(&session->mutex);
151 return put_user(temp, (int __user *)arg); 157 return put_user(temp, argp);
152 case VMCP_SETBUF: 158 case VMCP_SETBUF:
153 free_pages((unsigned long)session->response, 159 free_pages((unsigned long)session->response,
154 get_order(session->bufsize)); 160 get_order(session->bufsize));
155 session->response=NULL; 161 session->response=NULL;
156 temp = get_user(session->bufsize, (int __user *)arg); 162 temp = get_user(session->bufsize, argp);
157 if (get_order(session->bufsize) > 8) { 163 if (get_order(session->bufsize) > 8) {
158 session->bufsize = PAGE_SIZE; 164 session->bufsize = PAGE_SIZE;
159 temp = -EINVAL; 165 temp = -EINVAL;
@@ -163,7 +169,7 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
163 case VMCP_GETSIZE: 169 case VMCP_GETSIZE:
164 temp = session->resp_size; 170 temp = session->resp_size;
165 mutex_unlock(&session->mutex); 171 mutex_unlock(&session->mutex);
166 return put_user(temp, (int __user *)arg); 172 return put_user(temp, argp);
167 default: 173 default:
168 mutex_unlock(&session->mutex); 174 mutex_unlock(&session->mutex);
169 return -ENOIOCTLCMD; 175 return -ENOIOCTLCMD;
diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile
index d033414f7599..e1b700a19648 100644
--- a/drivers/s390/cio/Makefile
+++ b/drivers/s390/cio/Makefile
@@ -10,5 +10,5 @@ obj-y += ccw_device.o cmf.o
10obj-$(CONFIG_CHSC_SCH) += chsc_sch.o 10obj-$(CONFIG_CHSC_SCH) += chsc_sch.o
11obj-$(CONFIG_CCWGROUP) += ccwgroup.o 11obj-$(CONFIG_CCWGROUP) += ccwgroup.o
12 12
13qdio-objs := qdio_main.o qdio_thinint.o qdio_debug.o qdio_perf.o qdio_setup.o 13qdio-objs := qdio_main.o qdio_thinint.o qdio_debug.o qdio_setup.o
14obj-$(CONFIG_QDIO) += qdio.o 14obj-$(CONFIG_QDIO) += qdio.o
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index cc5144b6f9d9..c84ac9443079 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -12,6 +12,7 @@
12#include <linux/uaccess.h> 12#include <linux/uaccess.h>
13#include <linux/miscdevice.h> 13#include <linux/miscdevice.h>
14 14
15#include <asm/compat.h>
15#include <asm/cio.h> 16#include <asm/cio.h>
16#include <asm/chsc.h> 17#include <asm/chsc.h>
17#include <asm/isc.h> 18#include <asm/isc.h>
@@ -770,24 +771,30 @@ out_free:
770static long chsc_ioctl(struct file *filp, unsigned int cmd, 771static long chsc_ioctl(struct file *filp, unsigned int cmd,
771 unsigned long arg) 772 unsigned long arg)
772{ 773{
774 void __user *argp;
775
773 CHSC_MSG(2, "chsc_ioctl called, cmd=%x\n", cmd); 776 CHSC_MSG(2, "chsc_ioctl called, cmd=%x\n", cmd);
777 if (is_compat_task())
778 argp = compat_ptr(arg);
779 else
780 argp = (void __user *)arg;
774 switch (cmd) { 781 switch (cmd) {
775 case CHSC_START: 782 case CHSC_START:
776 return chsc_ioctl_start((void __user *)arg); 783 return chsc_ioctl_start(argp);
777 case CHSC_INFO_CHANNEL_PATH: 784 case CHSC_INFO_CHANNEL_PATH:
778 return chsc_ioctl_info_channel_path((void __user *)arg); 785 return chsc_ioctl_info_channel_path(argp);
779 case CHSC_INFO_CU: 786 case CHSC_INFO_CU:
780 return chsc_ioctl_info_cu((void __user *)arg); 787 return chsc_ioctl_info_cu(argp);
781 case CHSC_INFO_SCH_CU: 788 case CHSC_INFO_SCH_CU:
782 return chsc_ioctl_info_sch_cu((void __user *)arg); 789 return chsc_ioctl_info_sch_cu(argp);
783 case CHSC_INFO_CI: 790 case CHSC_INFO_CI:
784 return chsc_ioctl_conf_info((void __user *)arg); 791 return chsc_ioctl_conf_info(argp);
785 case CHSC_INFO_CCL: 792 case CHSC_INFO_CCL:
786 return chsc_ioctl_conf_comp_list((void __user *)arg); 793 return chsc_ioctl_conf_comp_list(argp);
787 case CHSC_INFO_CPD: 794 case CHSC_INFO_CPD:
788 return chsc_ioctl_chpd((void __user *)arg); 795 return chsc_ioctl_chpd(argp);
789 case CHSC_INFO_DCAL: 796 case CHSC_INFO_DCAL:
790 return chsc_ioctl_dcal((void __user *)arg); 797 return chsc_ioctl_dcal(argp);
791 default: /* unknown ioctl number */ 798 default: /* unknown ioctl number */
792 return -ENOIOCTLCMD; 799 return -ENOIOCTLCMD;
793 } 800 }
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index ff7748a9199d..44f2f6a97f33 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -182,6 +182,34 @@ struct scssc_area {
182 u32:32; 182 u32:32;
183} __attribute__ ((packed)); 183} __attribute__ ((packed));
184 184
185struct qdio_dev_perf_stat {
186 unsigned int adapter_int;
187 unsigned int qdio_int;
188 unsigned int pci_request_int;
189
190 unsigned int tasklet_inbound;
191 unsigned int tasklet_inbound_resched;
192 unsigned int tasklet_inbound_resched2;
193 unsigned int tasklet_outbound;
194
195 unsigned int siga_read;
196 unsigned int siga_write;
197 unsigned int siga_sync;
198
199 unsigned int inbound_call;
200 unsigned int inbound_handler;
201 unsigned int stop_polling;
202 unsigned int inbound_queue_full;
203 unsigned int outbound_call;
204 unsigned int outbound_handler;
205 unsigned int fast_requeue;
206 unsigned int target_full;
207 unsigned int eqbs;
208 unsigned int eqbs_partial;
209 unsigned int sqbs;
210 unsigned int sqbs_partial;
211};
212
185struct qdio_input_q { 213struct qdio_input_q {
186 /* input buffer acknowledgement flag */ 214 /* input buffer acknowledgement flag */
187 int polling; 215 int polling;
@@ -269,6 +297,7 @@ struct qdio_irq {
269 u32 *dsci; /* address of device state change indicator */ 297 u32 *dsci; /* address of device state change indicator */
270 struct ccw_device *cdev; 298 struct ccw_device *cdev;
271 struct dentry *debugfs_dev; 299 struct dentry *debugfs_dev;
300 struct dentry *debugfs_perf;
272 301
273 unsigned long int_parm; 302 unsigned long int_parm;
274 struct subchannel_id schid; 303 struct subchannel_id schid;
@@ -286,9 +315,10 @@ struct qdio_irq {
286 struct ciw aqueue; 315 struct ciw aqueue;
287 316
288 struct qdio_ssqd_desc ssqd_desc; 317 struct qdio_ssqd_desc ssqd_desc;
289
290 void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); 318 void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
291 319
320 struct qdio_dev_perf_stat perf_stat;
321 int perf_stat_enabled;
292 /* 322 /*
293 * Warning: Leave these members together at the end so they won't be 323 * Warning: Leave these members together at the end so they won't be
294 * cleared in qdio_setup_irq. 324 * cleared in qdio_setup_irq.
@@ -311,6 +341,10 @@ struct qdio_irq {
311 (irq->qib.qfmt == QDIO_IQDIO_QFMT || \ 341 (irq->qib.qfmt == QDIO_IQDIO_QFMT || \
312 css_general_characteristics.aif_osa) 342 css_general_characteristics.aif_osa)
313 343
344#define qperf(qdev,attr) qdev->perf_stat.attr
345#define qperf_inc(q,attr) if (q->irq_ptr->perf_stat_enabled) \
346 q->irq_ptr->perf_stat.attr++
347
314/* the highest iqdio queue is used for multicast */ 348/* the highest iqdio queue is used for multicast */
315static inline int multicast_outbound(struct qdio_q *q) 349static inline int multicast_outbound(struct qdio_q *q)
316{ 350{
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index 76769978285f..f49761ff9a00 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -55,13 +55,11 @@ static int qstat_show(struct seq_file *m, void *v)
55 if (!q) 55 if (!q)
56 return 0; 56 return 0;
57 57
58 seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci); 58 seq_printf(m, "DSCI: %d nr_used: %d\n",
59 seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used)); 59 *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
60 seq_printf(m, "ftc: %d\n", q->first_to_check); 60 seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move);
61 seq_printf(m, "last_move: %d\n", q->last_move); 61 seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
62 seq_printf(m, "polling: %d\n", q->u.in.polling); 62 q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count);
63 seq_printf(m, "ack start: %d\n", q->u.in.ack_start);
64 seq_printf(m, "ack count: %d\n", q->u.in.ack_count);
65 seq_printf(m, "slsb buffer states:\n"); 63 seq_printf(m, "slsb buffer states:\n");
66 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); 64 seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
67 65
@@ -110,7 +108,6 @@ static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
110 108
111 if (!q) 109 if (!q)
112 return 0; 110 return 0;
113
114 if (q->is_input_q) 111 if (q->is_input_q)
115 xchg(q->irq_ptr->dsci, 1); 112 xchg(q->irq_ptr->dsci, 1);
116 local_bh_disable(); 113 local_bh_disable();
@@ -134,6 +131,98 @@ static const struct file_operations debugfs_fops = {
134 .release = single_release, 131 .release = single_release,
135}; 132};
136 133
134static char *qperf_names[] = {
135 "Assumed adapter interrupts",
136 "QDIO interrupts",
137 "Requested PCIs",
138 "Inbound tasklet runs",
139 "Inbound tasklet resched",
140 "Inbound tasklet resched2",
141 "Outbound tasklet runs",
142 "SIGA read",
143 "SIGA write",
144 "SIGA sync",
145 "Inbound calls",
146 "Inbound handler",
147 "Inbound stop_polling",
148 "Inbound queue full",
149 "Outbound calls",
150 "Outbound handler",
151 "Outbound fast_requeue",
152 "Outbound target_full",
153 "QEBSM eqbs",
154 "QEBSM eqbs partial",
155 "QEBSM sqbs",
156 "QEBSM sqbs partial"
157};
158
159static int qperf_show(struct seq_file *m, void *v)
160{
161 struct qdio_irq *irq_ptr = m->private;
162 unsigned int *stat;
163 int i;
164
165 if (!irq_ptr)
166 return 0;
167 if (!irq_ptr->perf_stat_enabled) {
168 seq_printf(m, "disabled\n");
169 return 0;
170 }
171 stat = (unsigned int *)&irq_ptr->perf_stat;
172
173 for (i = 0; i < ARRAY_SIZE(qperf_names); i++)
174 seq_printf(m, "%26s:\t%u\n",
175 qperf_names[i], *(stat + i));
176 return 0;
177}
178
179static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf,
180 size_t count, loff_t *off)
181{
182 struct seq_file *seq = file->private_data;
183 struct qdio_irq *irq_ptr = seq->private;
184 unsigned long val;
185 char buf[8];
186 int ret;
187
188 if (!irq_ptr)
189 return 0;
190 if (count >= sizeof(buf))
191 return -EINVAL;
192 if (copy_from_user(&buf, ubuf, count))
193 return -EFAULT;
194 buf[count] = 0;
195
196 ret = strict_strtoul(buf, 10, &val);
197 if (ret < 0)
198 return ret;
199
200 switch (val) {
201 case 0:
202 irq_ptr->perf_stat_enabled = 0;
203 memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
204 break;
205 case 1:
206 irq_ptr->perf_stat_enabled = 1;
207 break;
208 }
209 return count;
210}
211
212static int qperf_seq_open(struct inode *inode, struct file *filp)
213{
214 return single_open(filp, qperf_show,
215 filp->f_path.dentry->d_inode->i_private);
216}
217
218static struct file_operations debugfs_perf_fops = {
219 .owner = THIS_MODULE,
220 .open = qperf_seq_open,
221 .read = seq_read,
222 .write = qperf_seq_write,
223 .llseek = seq_lseek,
224 .release = single_release,
225};
137static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev) 226static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
138{ 227{
139 char name[QDIO_DEBUGFS_NAME_LEN]; 228 char name[QDIO_DEBUGFS_NAME_LEN];
@@ -156,6 +245,14 @@ void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
156 debugfs_root); 245 debugfs_root);
157 if (IS_ERR(irq_ptr->debugfs_dev)) 246 if (IS_ERR(irq_ptr->debugfs_dev))
158 irq_ptr->debugfs_dev = NULL; 247 irq_ptr->debugfs_dev = NULL;
248
249 irq_ptr->debugfs_perf = debugfs_create_file("statistics",
250 S_IFREG | S_IRUGO | S_IWUSR,
251 irq_ptr->debugfs_dev, irq_ptr,
252 &debugfs_perf_fops);
253 if (IS_ERR(irq_ptr->debugfs_perf))
254 irq_ptr->debugfs_perf = NULL;
255
159 for_each_input_queue(irq_ptr, q, i) 256 for_each_input_queue(irq_ptr, q, i)
160 setup_debugfs_entry(q, cdev); 257 setup_debugfs_entry(q, cdev);
161 for_each_output_queue(irq_ptr, q, i) 258 for_each_output_queue(irq_ptr, q, i)
@@ -171,6 +268,7 @@ void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cd
171 debugfs_remove(q->debugfs_q); 268 debugfs_remove(q->debugfs_q);
172 for_each_output_queue(irq_ptr, q, i) 269 for_each_output_queue(irq_ptr, q, i)
173 debugfs_remove(q->debugfs_q); 270 debugfs_remove(q->debugfs_q);
271 debugfs_remove(irq_ptr->debugfs_perf);
174 debugfs_remove(irq_ptr->debugfs_dev); 272 debugfs_remove(irq_ptr->debugfs_dev);
175} 273}
176 274
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index b2275c5000e7..62b654af9237 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -22,7 +22,6 @@
22#include "device.h" 22#include "device.h"
23#include "qdio.h" 23#include "qdio.h"
24#include "qdio_debug.h" 24#include "qdio_debug.h"
25#include "qdio_perf.h"
26 25
27MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>,"\ 26MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>,"\
28 "Jan Glauber <jang@linux.vnet.ibm.com>"); 27 "Jan Glauber <jang@linux.vnet.ibm.com>");
@@ -126,7 +125,7 @@ static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
126 int rc; 125 int rc;
127 126
128 BUG_ON(!q->irq_ptr->sch_token); 127 BUG_ON(!q->irq_ptr->sch_token);
129 qdio_perf_stat_inc(&perf_stats.debug_eqbs_all); 128 qperf_inc(q, eqbs);
130 129
131 if (!q->is_input_q) 130 if (!q->is_input_q)
132 nr += q->irq_ptr->nr_input_qs; 131 nr += q->irq_ptr->nr_input_qs;
@@ -139,7 +138,7 @@ again:
139 * buffers later. 138 * buffers later.
140 */ 139 */
141 if ((ccq == 96) && (count != tmp_count)) { 140 if ((ccq == 96) && (count != tmp_count)) {
142 qdio_perf_stat_inc(&perf_stats.debug_eqbs_incomplete); 141 qperf_inc(q, eqbs_partial);
143 return (count - tmp_count); 142 return (count - tmp_count);
144 } 143 }
145 144
@@ -182,7 +181,7 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start,
182 return 0; 181 return 0;
183 182
184 BUG_ON(!q->irq_ptr->sch_token); 183 BUG_ON(!q->irq_ptr->sch_token);
185 qdio_perf_stat_inc(&perf_stats.debug_sqbs_all); 184 qperf_inc(q, sqbs);
186 185
187 if (!q->is_input_q) 186 if (!q->is_input_q)
188 nr += q->irq_ptr->nr_input_qs; 187 nr += q->irq_ptr->nr_input_qs;
@@ -191,7 +190,7 @@ again:
191 rc = qdio_check_ccq(q, ccq); 190 rc = qdio_check_ccq(q, ccq);
192 if (rc == 1) { 191 if (rc == 1) {
193 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq); 192 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq);
194 qdio_perf_stat_inc(&perf_stats.debug_sqbs_incomplete); 193 qperf_inc(q, sqbs_partial);
195 goto again; 194 goto again;
196 } 195 }
197 if (rc < 0) { 196 if (rc < 0) {
@@ -285,7 +284,7 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output,
285 return 0; 284 return 0;
286 285
287 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr); 286 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr);
288 qdio_perf_stat_inc(&perf_stats.siga_sync); 287 qperf_inc(q, siga_sync);
289 288
290 cc = do_siga_sync(q->irq_ptr->schid, output, input); 289 cc = do_siga_sync(q->irq_ptr->schid, output, input);
291 if (cc) 290 if (cc)
@@ -350,7 +349,7 @@ static inline int qdio_siga_input(struct qdio_q *q)
350 int cc; 349 int cc;
351 350
352 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-r:%1d", q->nr); 351 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-r:%1d", q->nr);
353 qdio_perf_stat_inc(&perf_stats.siga_in); 352 qperf_inc(q, siga_read);
354 353
355 cc = do_siga_input(q->irq_ptr->schid, q->mask); 354 cc = do_siga_input(q->irq_ptr->schid, q->mask);
356 if (cc) 355 if (cc)
@@ -382,7 +381,7 @@ static inline void qdio_stop_polling(struct qdio_q *q)
382 return; 381 return;
383 382
384 q->u.in.polling = 0; 383 q->u.in.polling = 0;
385 qdio_perf_stat_inc(&perf_stats.debug_stop_polling); 384 qperf_inc(q, stop_polling);
386 385
387 /* show the card that we are not polling anymore */ 386 /* show the card that we are not polling anymore */
388 if (is_qebsm(q)) { 387 if (is_qebsm(q)) {
@@ -400,7 +399,7 @@ static void announce_buffer_error(struct qdio_q *q, int count)
400 /* special handling for no target buffer empty */ 399 /* special handling for no target buffer empty */
401 if ((!q->is_input_q && 400 if ((!q->is_input_q &&
402 (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) { 401 (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) {
403 qdio_perf_stat_inc(&perf_stats.outbound_target_full); 402 qperf_inc(q, target_full);
404 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x", 403 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x",
405 q->first_to_check); 404 q->first_to_check);
406 return; 405 return;
@@ -487,7 +486,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
487 inbound_primed(q, count); 486 inbound_primed(q, count);
488 q->first_to_check = add_buf(q->first_to_check, count); 487 q->first_to_check = add_buf(q->first_to_check, count);
489 if (atomic_sub(count, &q->nr_buf_used) == 0) 488 if (atomic_sub(count, &q->nr_buf_used) == 0)
490 qdio_perf_stat_inc(&perf_stats.inbound_queue_full); 489 qperf_inc(q, inbound_queue_full);
491 break; 490 break;
492 case SLSB_P_INPUT_ERROR: 491 case SLSB_P_INPUT_ERROR:
493 announce_buffer_error(q, count); 492 announce_buffer_error(q, count);
@@ -532,7 +531,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q)
532 qdio_siga_sync_q(q); 531 qdio_siga_sync_q(q);
533 get_buf_state(q, q->first_to_check, &state, 0); 532 get_buf_state(q, q->first_to_check, &state, 0);
534 533
535 if (state == SLSB_P_INPUT_PRIMED) 534 if (state == SLSB_P_INPUT_PRIMED || state == SLSB_P_INPUT_ERROR)
536 /* more work coming */ 535 /* more work coming */
537 return 0; 536 return 0;
538 537
@@ -567,9 +566,10 @@ static void qdio_kick_handler(struct qdio_q *q)
567 count = sub_buf(end, start); 566 count = sub_buf(end, start);
568 567
569 if (q->is_input_q) { 568 if (q->is_input_q) {
570 qdio_perf_stat_inc(&perf_stats.inbound_handler); 569 qperf_inc(q, inbound_handler);
571 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count); 570 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count);
572 } else 571 } else
572 qperf_inc(q, outbound_handler);
573 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", 573 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x",
574 start, count); 574 start, count);
575 575
@@ -583,24 +583,28 @@ static void qdio_kick_handler(struct qdio_q *q)
583 583
584static void __qdio_inbound_processing(struct qdio_q *q) 584static void __qdio_inbound_processing(struct qdio_q *q)
585{ 585{
586 qdio_perf_stat_inc(&perf_stats.tasklet_inbound); 586 qperf_inc(q, tasklet_inbound);
587again: 587again:
588 if (!qdio_inbound_q_moved(q)) 588 if (!qdio_inbound_q_moved(q))
589 return; 589 return;
590 590
591 qdio_kick_handler(q); 591 qdio_kick_handler(q);
592 592
593 if (!qdio_inbound_q_done(q)) 593 if (!qdio_inbound_q_done(q)) {
594 /* means poll time is not yet over */ 594 /* means poll time is not yet over */
595 qperf_inc(q, tasklet_inbound_resched);
595 goto again; 596 goto again;
597 }
596 598
597 qdio_stop_polling(q); 599 qdio_stop_polling(q);
598 /* 600 /*
599 * We need to check again to not lose initiative after 601 * We need to check again to not lose initiative after
600 * resetting the ACK state. 602 * resetting the ACK state.
601 */ 603 */
602 if (!qdio_inbound_q_done(q)) 604 if (!qdio_inbound_q_done(q)) {
605 qperf_inc(q, tasklet_inbound_resched2);
603 goto again; 606 goto again;
607 }
604} 608}
605 609
606void qdio_inbound_processing(unsigned long data) 610void qdio_inbound_processing(unsigned long data)
@@ -688,7 +692,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q)
688 return 0; 692 return 0;
689 693
690 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr); 694 DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr);
691 qdio_perf_stat_inc(&perf_stats.siga_out); 695 qperf_inc(q, siga_write);
692 696
693 cc = qdio_siga_output(q, &busy_bit); 697 cc = qdio_siga_output(q, &busy_bit);
694 switch (cc) { 698 switch (cc) {
@@ -711,7 +715,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q)
711 715
712static void __qdio_outbound_processing(struct qdio_q *q) 716static void __qdio_outbound_processing(struct qdio_q *q)
713{ 717{
714 qdio_perf_stat_inc(&perf_stats.tasklet_outbound); 718 qperf_inc(q, tasklet_outbound);
715 BUG_ON(atomic_read(&q->nr_buf_used) < 0); 719 BUG_ON(atomic_read(&q->nr_buf_used) < 0);
716 720
717 if (qdio_outbound_q_moved(q)) 721 if (qdio_outbound_q_moved(q))
@@ -739,12 +743,9 @@ static void __qdio_outbound_processing(struct qdio_q *q)
739 */ 743 */
740 if (qdio_outbound_q_done(q)) 744 if (qdio_outbound_q_done(q))
741 del_timer(&q->u.out.timer); 745 del_timer(&q->u.out.timer);
742 else { 746 else
743 if (!timer_pending(&q->u.out.timer)) { 747 if (!timer_pending(&q->u.out.timer))
744 mod_timer(&q->u.out.timer, jiffies + 10 * HZ); 748 mod_timer(&q->u.out.timer, jiffies + 10 * HZ);
745 qdio_perf_stat_inc(&perf_stats.debug_tl_out_timer);
746 }
747 }
748 return; 749 return;
749 750
750sched: 751sched:
@@ -784,7 +785,7 @@ static inline void qdio_check_outbound_after_thinint(struct qdio_q *q)
784 785
785static void __tiqdio_inbound_processing(struct qdio_q *q) 786static void __tiqdio_inbound_processing(struct qdio_q *q)
786{ 787{
787 qdio_perf_stat_inc(&perf_stats.thinint_inbound); 788 qperf_inc(q, tasklet_inbound);
788 qdio_sync_after_thinint(q); 789 qdio_sync_after_thinint(q);
789 790
790 /* 791 /*
@@ -799,7 +800,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q)
799 qdio_kick_handler(q); 800 qdio_kick_handler(q);
800 801
801 if (!qdio_inbound_q_done(q)) { 802 if (!qdio_inbound_q_done(q)) {
802 qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop); 803 qperf_inc(q, tasklet_inbound_resched);
803 if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { 804 if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) {
804 tasklet_schedule(&q->tasklet); 805 tasklet_schedule(&q->tasklet);
805 return; 806 return;
@@ -812,7 +813,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q)
812 * resetting the ACK state. 813 * resetting the ACK state.
813 */ 814 */
814 if (!qdio_inbound_q_done(q)) { 815 if (!qdio_inbound_q_done(q)) {
815 qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop2); 816 qperf_inc(q, tasklet_inbound_resched2);
816 if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) 817 if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED))
817 tasklet_schedule(&q->tasklet); 818 tasklet_schedule(&q->tasklet);
818 } 819 }
@@ -851,8 +852,6 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
851 if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) 852 if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
852 return; 853 return;
853 854
854 qdio_perf_stat_inc(&perf_stats.pci_int);
855
856 for_each_input_queue(irq_ptr, q, i) 855 for_each_input_queue(irq_ptr, q, i)
857 tasklet_schedule(&q->tasklet); 856 tasklet_schedule(&q->tasklet);
858 857
@@ -923,8 +922,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
923 struct qdio_irq *irq_ptr = cdev->private->qdio_data; 922 struct qdio_irq *irq_ptr = cdev->private->qdio_data;
924 int cstat, dstat; 923 int cstat, dstat;
925 924
926 qdio_perf_stat_inc(&perf_stats.qdio_int);
927
928 if (!intparm || !irq_ptr) { 925 if (!intparm || !irq_ptr) {
929 DBF_ERROR("qint:%4x", cdev->private->schid.sch_no); 926 DBF_ERROR("qint:%4x", cdev->private->schid.sch_no);
930 return; 927 return;
@@ -963,6 +960,8 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
963 qdio_handle_activate_check(cdev, intparm, cstat, 960 qdio_handle_activate_check(cdev, intparm, cstat,
964 dstat); 961 dstat);
965 break; 962 break;
963 case QDIO_IRQ_STATE_STOPPED:
964 break;
966 default: 965 default:
967 WARN_ON(1); 966 WARN_ON(1);
968 } 967 }
@@ -1383,6 +1382,8 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
1383{ 1382{
1384 int used, diff; 1383 int used, diff;
1385 1384
1385 qperf_inc(q, inbound_call);
1386
1386 if (!q->u.in.polling) 1387 if (!q->u.in.polling)
1387 goto set; 1388 goto set;
1388 1389
@@ -1438,14 +1439,16 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
1438 unsigned char state; 1439 unsigned char state;
1439 int used, rc = 0; 1440 int used, rc = 0;
1440 1441
1441 qdio_perf_stat_inc(&perf_stats.outbound_handler); 1442 qperf_inc(q, outbound_call);
1442 1443
1443 count = set_buf_states(q, bufnr, SLSB_CU_OUTPUT_PRIMED, count); 1444 count = set_buf_states(q, bufnr, SLSB_CU_OUTPUT_PRIMED, count);
1444 used = atomic_add_return(count, &q->nr_buf_used); 1445 used = atomic_add_return(count, &q->nr_buf_used);
1445 BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q); 1446 BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q);
1446 1447
1447 if (callflags & QDIO_FLAG_PCI_OUT) 1448 if (callflags & QDIO_FLAG_PCI_OUT) {
1448 q->u.out.pci_out_enabled = 1; 1449 q->u.out.pci_out_enabled = 1;
1450 qperf_inc(q, pci_request_int);
1451 }
1449 else 1452 else
1450 q->u.out.pci_out_enabled = 0; 1453 q->u.out.pci_out_enabled = 0;
1451 1454
@@ -1484,7 +1487,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
1484 if (state != SLSB_CU_OUTPUT_PRIMED) 1487 if (state != SLSB_CU_OUTPUT_PRIMED)
1485 rc = qdio_kick_outbound_q(q); 1488 rc = qdio_kick_outbound_q(q);
1486 else 1489 else
1487 qdio_perf_stat_inc(&perf_stats.fast_requeue); 1490 qperf_inc(q, fast_requeue);
1488 1491
1489out: 1492out:
1490 tasklet_schedule(&q->tasklet); 1493 tasklet_schedule(&q->tasklet);
@@ -1540,16 +1543,11 @@ static int __init init_QDIO(void)
1540 rc = qdio_debug_init(); 1543 rc = qdio_debug_init();
1541 if (rc) 1544 if (rc)
1542 goto out_ti; 1545 goto out_ti;
1543 rc = qdio_setup_perf_stats();
1544 if (rc)
1545 goto out_debug;
1546 rc = tiqdio_register_thinints(); 1546 rc = tiqdio_register_thinints();
1547 if (rc) 1547 if (rc)
1548 goto out_perf; 1548 goto out_debug;
1549 return 0; 1549 return 0;
1550 1550
1551out_perf:
1552 qdio_remove_perf_stats();
1553out_debug: 1551out_debug:
1554 qdio_debug_exit(); 1552 qdio_debug_exit();
1555out_ti: 1553out_ti:
@@ -1563,7 +1561,6 @@ static void __exit exit_QDIO(void)
1563{ 1561{
1564 tiqdio_unregister_thinints(); 1562 tiqdio_unregister_thinints();
1565 tiqdio_free_memory(); 1563 tiqdio_free_memory();
1566 qdio_remove_perf_stats();
1567 qdio_debug_exit(); 1564 qdio_debug_exit();
1568 qdio_setup_exit(); 1565 qdio_setup_exit();
1569} 1566}
diff --git a/drivers/s390/cio/qdio_perf.c b/drivers/s390/cio/qdio_perf.c
deleted file mode 100644
index 54f7c325a3e6..000000000000
--- a/drivers/s390/cio/qdio_perf.c
+++ /dev/null
@@ -1,149 +0,0 @@
1/*
2 * drivers/s390/cio/qdio_perf.c
3 *
4 * Copyright IBM Corp. 2008
5 *
6 * Author: Jan Glauber (jang@linux.vnet.ibm.com)
7 */
8#include <linux/kernel.h>
9#include <linux/proc_fs.h>
10#include <linux/seq_file.h>
11#include <asm/ccwdev.h>
12
13#include "cio.h"
14#include "css.h"
15#include "device.h"
16#include "ioasm.h"
17#include "chsc.h"
18#include "qdio_debug.h"
19#include "qdio_perf.h"
20
21int qdio_performance_stats;
22struct qdio_perf_stats perf_stats;
23
24#ifdef CONFIG_PROC_FS
25static struct proc_dir_entry *qdio_perf_pde;
26#endif
27
28/*
29 * procfs functions
30 */
31static int qdio_perf_proc_show(struct seq_file *m, void *v)
32{
33 seq_printf(m, "Number of qdio interrupts\t\t\t: %li\n",
34 (long)atomic_long_read(&perf_stats.qdio_int));
35 seq_printf(m, "Number of PCI interrupts\t\t\t: %li\n",
36 (long)atomic_long_read(&perf_stats.pci_int));
37 seq_printf(m, "Number of adapter interrupts\t\t\t: %li\n",
38 (long)atomic_long_read(&perf_stats.thin_int));
39 seq_printf(m, "\n");
40 seq_printf(m, "Inbound tasklet runs\t\t\t\t: %li\n",
41 (long)atomic_long_read(&perf_stats.tasklet_inbound));
42 seq_printf(m, "Outbound tasklet runs\t\t\t\t: %li\n",
43 (long)atomic_long_read(&perf_stats.tasklet_outbound));
44 seq_printf(m, "Adapter interrupt tasklet runs/loops\t\t: %li/%li\n",
45 (long)atomic_long_read(&perf_stats.tasklet_thinint),
46 (long)atomic_long_read(&perf_stats.tasklet_thinint_loop));
47 seq_printf(m, "Adapter interrupt inbound tasklet runs/loops\t: %li/%li\n",
48 (long)atomic_long_read(&perf_stats.thinint_inbound),
49 (long)atomic_long_read(&perf_stats.thinint_inbound_loop));
50 seq_printf(m, "\n");
51 seq_printf(m, "Number of SIGA In issued\t\t\t: %li\n",
52 (long)atomic_long_read(&perf_stats.siga_in));
53 seq_printf(m, "Number of SIGA Out issued\t\t\t: %li\n",
54 (long)atomic_long_read(&perf_stats.siga_out));
55 seq_printf(m, "Number of SIGA Sync issued\t\t\t: %li\n",
56 (long)atomic_long_read(&perf_stats.siga_sync));
57 seq_printf(m, "\n");
58 seq_printf(m, "Number of inbound transfers\t\t\t: %li\n",
59 (long)atomic_long_read(&perf_stats.inbound_handler));
60 seq_printf(m, "Number of outbound transfers\t\t\t: %li\n",
61 (long)atomic_long_read(&perf_stats.outbound_handler));
62 seq_printf(m, "\n");
63 seq_printf(m, "Number of fast requeues (outg. SBAL w/o SIGA)\t: %li\n",
64 (long)atomic_long_read(&perf_stats.fast_requeue));
65 seq_printf(m, "Number of outbound target full condition\t: %li\n",
66 (long)atomic_long_read(&perf_stats.outbound_target_full));
67 seq_printf(m, "Number of inbound queue full condition\t\t: %li\n",
68 (long)atomic_long_read(&perf_stats.inbound_queue_full));
69 seq_printf(m, "Number of outbound tasklet mod_timer calls\t: %li\n",
70 (long)atomic_long_read(&perf_stats.debug_tl_out_timer));
71 seq_printf(m, "Number of stop polling calls\t\t\t: %li\n",
72 (long)atomic_long_read(&perf_stats.debug_stop_polling));
73 seq_printf(m, "AI inbound tasklet loops after stop polling\t: %li\n",
74 (long)atomic_long_read(&perf_stats.thinint_inbound_loop2));
75 seq_printf(m, "QEBSM EQBS total/incomplete\t\t\t: %li/%li\n",
76 (long)atomic_long_read(&perf_stats.debug_eqbs_all),
77 (long)atomic_long_read(&perf_stats.debug_eqbs_incomplete));
78 seq_printf(m, "QEBSM SQBS total/incomplete\t\t\t: %li/%li\n",
79 (long)atomic_long_read(&perf_stats.debug_sqbs_all),
80 (long)atomic_long_read(&perf_stats.debug_sqbs_incomplete));
81 seq_printf(m, "\n");
82 return 0;
83}
84static int qdio_perf_seq_open(struct inode *inode, struct file *filp)
85{
86 return single_open(filp, qdio_perf_proc_show, NULL);
87}
88
89static const struct file_operations qdio_perf_proc_fops = {
90 .owner = THIS_MODULE,
91 .open = qdio_perf_seq_open,
92 .read = seq_read,
93 .llseek = seq_lseek,
94 .release = single_release,
95};
96
97/*
98 * sysfs functions
99 */
100static ssize_t qdio_perf_stats_show(struct bus_type *bus, char *buf)
101{
102 return sprintf(buf, "%i\n", qdio_performance_stats ? 1 : 0);
103}
104
105static ssize_t qdio_perf_stats_store(struct bus_type *bus,
106 const char *buf, size_t count)
107{
108 unsigned long i;
109
110 if (strict_strtoul(buf, 16, &i) != 0)
111 return -EINVAL;
112 if ((i != 0) && (i != 1))
113 return -EINVAL;
114 if (i == qdio_performance_stats)
115 return count;
116
117 qdio_performance_stats = i;
118 /* reset performance statistics */
119 if (i == 0)
120 memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
121 return count;
122}
123
124static BUS_ATTR(qdio_performance_stats, 0644, qdio_perf_stats_show,
125 qdio_perf_stats_store);
126
127int __init qdio_setup_perf_stats(void)
128{
129 int rc;
130
131 rc = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
132 if (rc)
133 return rc;
134
135#ifdef CONFIG_PROC_FS
136 memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
137 qdio_perf_pde = proc_create("qdio_perf", S_IFREG | S_IRUGO,
138 NULL, &qdio_perf_proc_fops);
139#endif
140 return 0;
141}
142
143void qdio_remove_perf_stats(void)
144{
145#ifdef CONFIG_PROC_FS
146 remove_proc_entry("qdio_perf", NULL);
147#endif
148 bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
149}
diff --git a/drivers/s390/cio/qdio_perf.h b/drivers/s390/cio/qdio_perf.h
deleted file mode 100644
index 12454231dc8b..000000000000
--- a/drivers/s390/cio/qdio_perf.h
+++ /dev/null
@@ -1,62 +0,0 @@
1/*
2 * drivers/s390/cio/qdio_perf.h
3 *
4 * Copyright IBM Corp. 2008
5 *
6 * Author: Jan Glauber (jang@linux.vnet.ibm.com)
7 */
8#ifndef QDIO_PERF_H
9#define QDIO_PERF_H
10
11#include <linux/types.h>
12#include <asm/atomic.h>
13
14struct qdio_perf_stats {
15 /* interrupt handler calls */
16 atomic_long_t qdio_int;
17 atomic_long_t pci_int;
18 atomic_long_t thin_int;
19
20 /* tasklet runs */
21 atomic_long_t tasklet_inbound;
22 atomic_long_t tasklet_outbound;
23 atomic_long_t tasklet_thinint;
24 atomic_long_t tasklet_thinint_loop;
25 atomic_long_t thinint_inbound;
26 atomic_long_t thinint_inbound_loop;
27 atomic_long_t thinint_inbound_loop2;
28
29 /* signal adapter calls */
30 atomic_long_t siga_out;
31 atomic_long_t siga_in;
32 atomic_long_t siga_sync;
33
34 /* misc */
35 atomic_long_t inbound_handler;
36 atomic_long_t outbound_handler;
37 atomic_long_t fast_requeue;
38 atomic_long_t outbound_target_full;
39 atomic_long_t inbound_queue_full;
40
41 /* for debugging */
42 atomic_long_t debug_tl_out_timer;
43 atomic_long_t debug_stop_polling;
44 atomic_long_t debug_eqbs_all;
45 atomic_long_t debug_eqbs_incomplete;
46 atomic_long_t debug_sqbs_all;
47 atomic_long_t debug_sqbs_incomplete;
48};
49
50extern struct qdio_perf_stats perf_stats;
51extern int qdio_performance_stats;
52
53static inline void qdio_perf_stat_inc(atomic_long_t *count)
54{
55 if (qdio_performance_stats)
56 atomic_long_inc(count);
57}
58
59int qdio_setup_perf_stats(void);
60void qdio_remove_perf_stats(void);
61
62#endif
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 981a77ea7ee2..091d904d3182 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -1,9 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/cio/thinint_qdio.c 2 * linux/drivers/s390/cio/thinint_qdio.c
3 * 3 *
4 * thin interrupt support for qdio 4 * Copyright 2000,2009 IBM Corp.
5 *
6 * Copyright 2000-2008 IBM Corp.
7 * Author(s): Utz Bacher <utz.bacher@de.ibm.com> 5 * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
8 * Cornelia Huck <cornelia.huck@de.ibm.com> 6 * Cornelia Huck <cornelia.huck@de.ibm.com>
9 * Jan Glauber <jang@linux.vnet.ibm.com> 7 * Jan Glauber <jang@linux.vnet.ibm.com>
@@ -19,7 +17,6 @@
19#include "ioasm.h" 17#include "ioasm.h"
20#include "qdio.h" 18#include "qdio.h"
21#include "qdio_debug.h" 19#include "qdio_debug.h"
22#include "qdio_perf.h"
23 20
24/* 21/*
25 * Restriction: only 63 iqdio subchannels would have its own indicator, 22 * Restriction: only 63 iqdio subchannels would have its own indicator,
@@ -132,8 +129,6 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data)
132{ 129{
133 struct qdio_q *q; 130 struct qdio_q *q;
134 131
135 qdio_perf_stat_inc(&perf_stats.thin_int);
136
137 /* 132 /*
138 * SVS only when needed: issue SVS to benefit from iqdio interrupt 133 * SVS only when needed: issue SVS to benefit from iqdio interrupt
139 * avoidance (SVS clears adapter interrupt suppression overwrite) 134 * avoidance (SVS clears adapter interrupt suppression overwrite)
@@ -154,6 +149,7 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data)
154 list_for_each_entry_rcu(q, &tiq_list, entry) 149 list_for_each_entry_rcu(q, &tiq_list, entry)
155 /* only process queues from changed sets */ 150 /* only process queues from changed sets */
156 if (*q->irq_ptr->dsci) { 151 if (*q->irq_ptr->dsci) {
152 qperf_inc(q, adapter_int);
157 153
158 /* only clear it if the indicator is non-shared */ 154 /* only clear it if the indicator is non-shared */
159 if (!shared_ind(q->irq_ptr)) 155 if (!shared_ind(q->irq_ptr))
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 0d4d18bdd45c..c68be24e27d9 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -393,10 +393,12 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
393 * u_mult_inv > 128 bytes. 393 * u_mult_inv > 128 bytes.
394 */ 394 */
395 if (copied == 0) { 395 if (copied == 0) {
396 int len; 396 unsigned int len;
397 spin_unlock_bh(&zcrypt_device_lock); 397 spin_unlock_bh(&zcrypt_device_lock);
398 /* len is max 256 / 2 - 120 = 8 */ 398 /* len is max 256 / 2 - 120 = 8 */
399 len = crt->inputdatalength / 2 - 120; 399 len = crt->inputdatalength / 2 - 120;
400 if (len > sizeof(z1))
401 return -EFAULT;
400 z1 = z2 = z3 = 0; 402 z1 = z2 = z3 = 0;
401 if (copy_from_user(&z1, crt->np_prime, len) || 403 if (copy_from_user(&z1, crt->np_prime, len) ||
402 copy_from_user(&z2, crt->bp_key, len) || 404 copy_from_user(&z2, crt->bp_key, len) ||
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index a23726a0735c..142f72a2ca5a 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -373,6 +373,8 @@ static int convert_type86(struct zcrypt_device *zdev,
373 zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD; 373 zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD;
374 return -EAGAIN; 374 return -EAGAIN;
375 } 375 }
376 if (service_rc == 8 && service_rs == 72)
377 return -EINVAL;
376 zdev->online = 0; 378 zdev->online = 0;
377 return -EAGAIN; /* repeat the request on a different device. */ 379 return -EAGAIN; /* repeat the request on a different device. */
378 } 380 }
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 79c120578e61..68f3e6204db8 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -470,6 +470,8 @@ static int convert_type86_ica(struct zcrypt_device *zdev,
470 } 470 }
471 if (service_rc == 12 && service_rs == 769) 471 if (service_rc == 12 && service_rs == 769)
472 return -EINVAL; 472 return -EINVAL;
473 if (service_rc == 8 && service_rs == 72)
474 return -EINVAL;
473 zdev->online = 0; 475 zdev->online = 0;
474 return -EAGAIN; /* repeat the request on a different device. */ 476 return -EAGAIN; /* repeat the request on a different device. */
475 } 477 }
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 3c77bfe0764c..147bb1a69aba 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -3398,7 +3398,7 @@ claw_init(void)
3398 goto out_err; 3398 goto out_err;
3399 } 3399 }
3400 CLAW_DBF_TEXT(2, setup, "init_mod"); 3400 CLAW_DBF_TEXT(2, setup, "init_mod");
3401 claw_root_dev = root_device_register("qeth"); 3401 claw_root_dev = root_device_register("claw");
3402 ret = IS_ERR(claw_root_dev) ? PTR_ERR(claw_root_dev) : 0; 3402 ret = IS_ERR(claw_root_dev) ? PTR_ERR(claw_root_dev) : 0;
3403 if (ret) 3403 if (ret)
3404 goto register_err; 3404 goto register_err;
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c
index f932400e980a..0eb6eefd2c1a 100644
--- a/drivers/s390/scsi/zfcp_cfdc.c
+++ b/drivers/s390/scsi/zfcp_cfdc.c
@@ -12,6 +12,7 @@
12 12
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/miscdevice.h> 14#include <linux/miscdevice.h>
15#include <asm/compat.h>
15#include <asm/ccwdev.h> 16#include <asm/ccwdev.h>
16#include "zfcp_def.h" 17#include "zfcp_def.h"
17#include "zfcp_ext.h" 18#include "zfcp_ext.h"
@@ -163,7 +164,7 @@ static void zfcp_cfdc_req_to_sense(struct zfcp_cfdc_data *data,
163} 164}
164 165
165static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, 166static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
166 unsigned long buffer) 167 unsigned long arg)
167{ 168{
168 struct zfcp_cfdc_data *data; 169 struct zfcp_cfdc_data *data;
169 struct zfcp_cfdc_data __user *data_user; 170 struct zfcp_cfdc_data __user *data_user;
@@ -175,7 +176,11 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
175 if (command != ZFCP_CFDC_IOC) 176 if (command != ZFCP_CFDC_IOC)
176 return -ENOTTY; 177 return -ENOTTY;
177 178
178 data_user = (void __user *) buffer; 179 if (is_compat_task())
180 data_user = compat_ptr(arg);
181 else
182 data_user = (void __user *)arg;
183
179 if (!data_user) 184 if (!data_user)
180 return -EINVAL; 185 return -EINVAL;
181 186
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 84450955ae11..7369c8911bcf 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -327,7 +327,7 @@ static void zfcp_dbf_hba_view_response(char **p,
327 break; 327 break;
328 zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd); 328 zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
329 zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial); 329 zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial);
330 p += sprintf(*p, "\n"); 330 *p += sprintf(*p, "\n");
331 break; 331 break;
332 332
333 case FSF_QTCB_OPEN_PORT_WITH_DID: 333 case FSF_QTCB_OPEN_PORT_WITH_DID:
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 03dec832b465..66bdb34143cb 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -108,6 +108,7 @@ extern void zfcp_fc_wka_ports_force_offline(struct zfcp_fc_wka_ports *);
108extern int zfcp_fc_gs_setup(struct zfcp_adapter *); 108extern int zfcp_fc_gs_setup(struct zfcp_adapter *);
109extern void zfcp_fc_gs_destroy(struct zfcp_adapter *); 109extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
110extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *); 110extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
111extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
111 112
112/* zfcp_fsf.c */ 113/* zfcp_fsf.c */
113extern int zfcp_fsf_open_port(struct zfcp_erp_action *); 114extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
@@ -129,9 +130,9 @@ extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
129extern int zfcp_fsf_status_read(struct zfcp_qdio *); 130extern int zfcp_fsf_status_read(struct zfcp_qdio *);
130extern int zfcp_status_read_refill(struct zfcp_adapter *adapter); 131extern int zfcp_status_read_refill(struct zfcp_adapter *adapter);
131extern int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *, struct zfcp_fsf_ct_els *, 132extern int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *, struct zfcp_fsf_ct_els *,
132 mempool_t *); 133 mempool_t *, unsigned int);
133extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32, 134extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32,
134 struct zfcp_fsf_ct_els *); 135 struct zfcp_fsf_ct_els *, unsigned int);
135extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *, 136extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
136 struct scsi_cmnd *); 137 struct scsi_cmnd *);
137extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); 138extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index ac5e3b7a3576..271399f62f1b 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -258,7 +258,8 @@ static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port,
258 gid_pn->gid_pn_req.gid_pn.fn_wwpn = port->wwpn; 258 gid_pn->gid_pn_req.gid_pn.fn_wwpn = port->wwpn;
259 259
260 ret = zfcp_fsf_send_ct(&adapter->gs->ds, &gid_pn->ct, 260 ret = zfcp_fsf_send_ct(&adapter->gs->ds, &gid_pn->ct,
261 adapter->pool.gid_pn_req); 261 adapter->pool.gid_pn_req,
262 ZFCP_FC_CTELS_TMO);
262 if (!ret) { 263 if (!ret) {
263 wait_for_completion(&completion); 264 wait_for_completion(&completion);
264 zfcp_fc_ns_gid_pn_eval(gid_pn); 265 zfcp_fc_ns_gid_pn_eval(gid_pn);
@@ -421,7 +422,8 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
421 hton24(adisc->adisc_req.adisc_port_id, 422 hton24(adisc->adisc_req.adisc_port_id,
422 fc_host_port_id(adapter->scsi_host)); 423 fc_host_port_id(adapter->scsi_host));
423 424
424 ret = zfcp_fsf_send_els(adapter, port->d_id, &adisc->els); 425 ret = zfcp_fsf_send_els(adapter, port->d_id, &adisc->els,
426 ZFCP_FC_CTELS_TMO);
425 if (ret) 427 if (ret)
426 kmem_cache_free(zfcp_data.adisc_cache, adisc); 428 kmem_cache_free(zfcp_data.adisc_cache, adisc);
427 429
@@ -532,7 +534,8 @@ static int zfcp_fc_send_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft,
532 ct->req = &gpn_ft->sg_req; 534 ct->req = &gpn_ft->sg_req;
533 ct->resp = gpn_ft->sg_resp; 535 ct->resp = gpn_ft->sg_resp;
534 536
535 ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct, NULL); 537 ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct, NULL,
538 ZFCP_FC_CTELS_TMO);
536 if (!ret) 539 if (!ret)
537 wait_for_completion(&completion); 540 wait_for_completion(&completion);
538 return ret; 541 return ret;
@@ -668,15 +671,52 @@ static void zfcp_fc_ct_els_job_handler(void *data)
668{ 671{
669 struct fc_bsg_job *job = data; 672 struct fc_bsg_job *job = data;
670 struct zfcp_fsf_ct_els *zfcp_ct_els = job->dd_data; 673 struct zfcp_fsf_ct_els *zfcp_ct_els = job->dd_data;
671 int status = zfcp_ct_els->status; 674 struct fc_bsg_reply *jr = job->reply;
672 int reply_status;
673 675
674 reply_status = status ? FC_CTELS_STATUS_REJECT : FC_CTELS_STATUS_OK; 676 jr->reply_payload_rcv_len = job->reply_payload.payload_len;
675 job->reply->reply_data.ctels_reply.status = reply_status; 677 jr->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
676 job->reply->reply_payload_rcv_len = job->reply_payload.payload_len; 678 jr->result = zfcp_ct_els->status ? -EIO : 0;
677 job->job_done(job); 679 job->job_done(job);
678} 680}
679 681
682static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job)
683{
684 u32 preamble_word1;
685 u8 gs_type;
686 struct zfcp_adapter *adapter;
687
688 preamble_word1 = job->request->rqst_data.r_ct.preamble_word1;
689 gs_type = (preamble_word1 & 0xff000000) >> 24;
690
691 adapter = (struct zfcp_adapter *) job->shost->hostdata[0];
692
693 switch (gs_type) {
694 case FC_FST_ALIAS:
695 return &adapter->gs->as;
696 case FC_FST_MGMT:
697 return &adapter->gs->ms;
698 case FC_FST_TIME:
699 return &adapter->gs->ts;
700 break;
701 case FC_FST_DIR:
702 return &adapter->gs->ds;
703 break;
704 default:
705 return NULL;
706 }
707}
708
709static void zfcp_fc_ct_job_handler(void *data)
710{
711 struct fc_bsg_job *job = data;
712 struct zfcp_fc_wka_port *wka_port;
713
714 wka_port = zfcp_fc_job_wka_port(job);
715 zfcp_fc_wka_port_put(wka_port);
716
717 zfcp_fc_ct_els_job_handler(data);
718}
719
680static int zfcp_fc_exec_els_job(struct fc_bsg_job *job, 720static int zfcp_fc_exec_els_job(struct fc_bsg_job *job,
681 struct zfcp_adapter *adapter) 721 struct zfcp_adapter *adapter)
682{ 722{
@@ -695,43 +735,27 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job,
695 } else 735 } else
696 d_id = ntoh24(job->request->rqst_data.h_els.port_id); 736 d_id = ntoh24(job->request->rqst_data.h_els.port_id);
697 737
698 return zfcp_fsf_send_els(adapter, d_id, els); 738 els->handler = zfcp_fc_ct_els_job_handler;
739 return zfcp_fsf_send_els(adapter, d_id, els, job->req->timeout / HZ);
699} 740}
700 741
701static int zfcp_fc_exec_ct_job(struct fc_bsg_job *job, 742static int zfcp_fc_exec_ct_job(struct fc_bsg_job *job,
702 struct zfcp_adapter *adapter) 743 struct zfcp_adapter *adapter)
703{ 744{
704 int ret; 745 int ret;
705 u8 gs_type;
706 struct zfcp_fsf_ct_els *ct = job->dd_data; 746 struct zfcp_fsf_ct_els *ct = job->dd_data;
707 struct zfcp_fc_wka_port *wka_port; 747 struct zfcp_fc_wka_port *wka_port;
708 u32 preamble_word1;
709 748
710 preamble_word1 = job->request->rqst_data.r_ct.preamble_word1; 749 wka_port = zfcp_fc_job_wka_port(job);
711 gs_type = (preamble_word1 & 0xff000000) >> 24; 750 if (!wka_port)
712 751 return -EINVAL;
713 switch (gs_type) {
714 case FC_FST_ALIAS:
715 wka_port = &adapter->gs->as;
716 break;
717 case FC_FST_MGMT:
718 wka_port = &adapter->gs->ms;
719 break;
720 case FC_FST_TIME:
721 wka_port = &adapter->gs->ts;
722 break;
723 case FC_FST_DIR:
724 wka_port = &adapter->gs->ds;
725 break;
726 default:
727 return -EINVAL; /* no such service */
728 }
729 752
730 ret = zfcp_fc_wka_port_get(wka_port); 753 ret = zfcp_fc_wka_port_get(wka_port);
731 if (ret) 754 if (ret)
732 return ret; 755 return ret;
733 756
734 ret = zfcp_fsf_send_ct(wka_port, ct, NULL); 757 ct->handler = zfcp_fc_ct_job_handler;
758 ret = zfcp_fsf_send_ct(wka_port, ct, NULL, job->req->timeout / HZ);
735 if (ret) 759 if (ret)
736 zfcp_fc_wka_port_put(wka_port); 760 zfcp_fc_wka_port_put(wka_port);
737 761
@@ -752,7 +776,6 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
752 776
753 ct_els->req = job->request_payload.sg_list; 777 ct_els->req = job->request_payload.sg_list;
754 ct_els->resp = job->reply_payload.sg_list; 778 ct_els->resp = job->reply_payload.sg_list;
755 ct_els->handler = zfcp_fc_ct_els_job_handler;
756 ct_els->handler_data = job; 779 ct_els->handler_data = job;
757 780
758 switch (job->request->msgcode) { 781 switch (job->request->msgcode) {
@@ -767,6 +790,12 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
767 } 790 }
768} 791}
769 792
793int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *job)
794{
795 /* hardware tracks timeout, reset bsg timeout to not interfere */
796 return -EAGAIN;
797}
798
770int zfcp_fc_gs_setup(struct zfcp_adapter *adapter) 799int zfcp_fc_gs_setup(struct zfcp_adapter *adapter)
771{ 800{
772 struct zfcp_fc_wka_ports *wka_ports; 801 struct zfcp_fc_wka_ports *wka_ports;
diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h
index cb2a3669a384..0747b087390d 100644
--- a/drivers/s390/scsi/zfcp_fc.h
+++ b/drivers/s390/scsi/zfcp_fc.h
@@ -27,6 +27,8 @@
27#define ZFCP_FC_GPN_FT_MAX_ENT (ZFCP_FC_GPN_FT_NUM_BUFS * \ 27#define ZFCP_FC_GPN_FT_MAX_ENT (ZFCP_FC_GPN_FT_NUM_BUFS * \
28 (ZFCP_FC_GPN_FT_ENT_PAGE + 1)) 28 (ZFCP_FC_GPN_FT_ENT_PAGE + 1))
29 29
30#define ZFCP_FC_CTELS_TMO (2 * FC_DEF_R_A_TOV / 1000)
31
30/** 32/**
31 * struct zfcp_fc_gid_pn_req - container for ct header plus gid_pn request 33 * struct zfcp_fc_gid_pn_req - container for ct header plus gid_pn request
32 * @ct_hdr: FC GS common transport header 34 * @ct_hdr: FC GS common transport header
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 482dcd97aa5d..e8fb4d9baa8b 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1068,20 +1068,20 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
1068static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req, 1068static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
1069 struct scatterlist *sg_req, 1069 struct scatterlist *sg_req,
1070 struct scatterlist *sg_resp, 1070 struct scatterlist *sg_resp,
1071 int max_sbals) 1071 int max_sbals, unsigned int timeout)
1072{ 1072{
1073 int ret; 1073 int ret;
1074 unsigned int fcp_chan_timeout;
1075 1074
1076 ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp, max_sbals); 1075 ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp, max_sbals);
1077 if (ret) 1076 if (ret)
1078 return ret; 1077 return ret;
1079 1078
1080 /* common settings for ct/gs and els requests */ 1079 /* common settings for ct/gs and els requests */
1081 fcp_chan_timeout = 2 * FC_DEF_R_A_TOV / 1000; 1080 if (timeout > 255)
1081 timeout = 255; /* max value accepted by hardware */
1082 req->qtcb->bottom.support.service_class = FSF_CLASS_3; 1082 req->qtcb->bottom.support.service_class = FSF_CLASS_3;
1083 req->qtcb->bottom.support.timeout = fcp_chan_timeout; 1083 req->qtcb->bottom.support.timeout = timeout;
1084 zfcp_fsf_start_timer(req, (fcp_chan_timeout + 10) * HZ); 1084 zfcp_fsf_start_timer(req, (timeout + 10) * HZ);
1085 1085
1086 return 0; 1086 return 0;
1087} 1087}
@@ -1092,7 +1092,8 @@ static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
1092 * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req 1092 * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req
1093 */ 1093 */
1094int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port, 1094int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
1095 struct zfcp_fsf_ct_els *ct, mempool_t *pool) 1095 struct zfcp_fsf_ct_els *ct, mempool_t *pool,
1096 unsigned int timeout)
1096{ 1097{
1097 struct zfcp_qdio *qdio = wka_port->adapter->qdio; 1098 struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1098 struct zfcp_fsf_req *req; 1099 struct zfcp_fsf_req *req;
@@ -1111,7 +1112,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
1111 1112
1112 req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 1113 req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1113 ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp, 1114 ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp,
1114 FSF_MAX_SBALS_PER_REQ); 1115 FSF_MAX_SBALS_PER_REQ, timeout);
1115 if (ret) 1116 if (ret)
1116 goto failed_send; 1117 goto failed_send;
1117 1118
@@ -1188,7 +1189,7 @@ skip_fsfstatus:
1188 * @els: pointer to struct zfcp_send_els with data for the command 1189 * @els: pointer to struct zfcp_send_els with data for the command
1189 */ 1190 */
1190int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id, 1191int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
1191 struct zfcp_fsf_ct_els *els) 1192 struct zfcp_fsf_ct_els *els, unsigned int timeout)
1192{ 1193{
1193 struct zfcp_fsf_req *req; 1194 struct zfcp_fsf_req *req;
1194 struct zfcp_qdio *qdio = adapter->qdio; 1195 struct zfcp_qdio *qdio = adapter->qdio;
@@ -1206,7 +1207,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
1206 } 1207 }
1207 1208
1208 req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; 1209 req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1209 ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, 2); 1210 ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, 2, timeout);
1210 1211
1211 if (ret) 1212 if (ret)
1212 goto failed_send; 1213 goto failed_send;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 771cc536a989..8e6fc68d6bd4 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -652,6 +652,7 @@ struct fc_function_template zfcp_transport_functions = {
652 .show_host_port_state = 1, 652 .show_host_port_state = 1,
653 .show_host_active_fc4s = 1, 653 .show_host_active_fc4s = 1,
654 .bsg_request = zfcp_fc_exec_bsg_job, 654 .bsg_request = zfcp_fc_exec_bsg_job,
655 .bsg_timeout = zfcp_fc_timeout_bsg_job,
655 /* no functions registered for following dynamic attributes but 656 /* no functions registered for following dynamic attributes but
656 directly set by LLDD */ 657 directly set by LLDD */
657 .show_host_port_type = 1, 658 .show_host_port_type = 1,