aboutsummaryrefslogtreecommitdiff
path: root/drivers/s390
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-08-29 16:40:27 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-08-29 16:40:27 -0400
commitc1b054d03f5b31c33eaa0b267c629b118eaf3790 (patch)
tree9333907ca767be24fcb3667877242976c3e3c8dd /drivers/s390
parent559fb51ba7e66fe298b8355fabde1275b7def35f (diff)
parentbf4e70e54cf31dcca48d279c7f7e71328eebe749 (diff)
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/Kconfig7
-rw-r--r--drivers/s390/block/dasd.c36
-rw-r--r--drivers/s390/block/dasd_fba.c4
-rw-r--r--drivers/s390/block/dasd_proc.c3
-rw-r--r--drivers/s390/block/dcssblk.c48
-rw-r--r--drivers/s390/char/Makefile1
-rw-r--r--drivers/s390/char/con3215.c4
-rw-r--r--drivers/s390/char/con3270.c4
-rw-r--r--drivers/s390/char/tape.h7
-rw-r--r--drivers/s390/char/tape_34xx.c6
-rw-r--r--drivers/s390/char/tape_core.c301
-rw-r--r--drivers/s390/char/tape_proc.c1
-rw-r--r--drivers/s390/char/vmcp.c219
-rw-r--r--drivers/s390/char/vmcp.h30
-rw-r--r--drivers/s390/char/vmlogrdr.c10
-rw-r--r--drivers/s390/char/vmwatchdog.c6
-rw-r--r--drivers/s390/cio/ccwgroup.c30
-rw-r--r--drivers/s390/cio/chsc.c10
-rw-r--r--drivers/s390/cio/cio.c8
-rw-r--r--drivers/s390/cio/css.c34
-rw-r--r--drivers/s390/cio/device.c84
-rw-r--r--drivers/s390/cio/device_fsm.c3
-rw-r--r--drivers/s390/cio/device_status.c5
-rw-r--r--drivers/s390/cio/qdio.c38
-rw-r--r--drivers/s390/cio/qdio.h16
-rw-r--r--drivers/s390/crypto/z90crypt.h9
-rw-r--r--drivers/s390/net/claw.c8
-rw-r--r--drivers/s390/net/ctcdbug.c10
-rw-r--r--drivers/s390/net/ctcdbug.h10
-rw-r--r--drivers/s390/net/ctctty.c6
-rw-r--r--drivers/s390/net/iucv.h6
-rw-r--r--drivers/s390/net/lcs.c8
-rw-r--r--drivers/s390/net/netiucv.c12
-rw-r--r--drivers/s390/net/qeth.h40
-rw-r--r--drivers/s390/net/qeth_main.c40
-rw-r--r--drivers/s390/net/qeth_proc.c126
-rw-r--r--drivers/s390/net/smsgiucv.c4
-rw-r--r--drivers/s390/s390mach.c321
-rw-r--r--drivers/s390/s390mach.h35
-rw-r--r--drivers/s390/scsi/zfcp_aux.c28
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c10
-rw-r--r--drivers/s390/scsi/zfcp_def.h2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c25
-rw-r--r--drivers/s390/scsi/zfcp_ext.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c1
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c25
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_port.c2
47 files changed, 1145 insertions, 500 deletions
diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig
index 96413c2cd1a..a86a650f3d6 100644
--- a/drivers/s390/Kconfig
+++ b/drivers/s390/Kconfig
@@ -187,6 +187,13 @@ config VMLOGRDR
*SYMPTOM.
This driver depends on the IUCV support driver.
+config VMCP
+ tristate "Support for the z/VM CP interface (VM only)"
+ help
+ Select this option if you want to be able to interact with the control
+ program on z/VM
+
+
config MONREADER
tristate "API for reading z/VM monitor service records"
depends on IUCV
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index ceeb3cf64a1..d5f53980749 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.164 $
+ * $Revision: 1.165 $
*/
#include <linux/config.h>
@@ -176,7 +176,7 @@ dasd_state_known_to_basic(struct dasd_device * device)
return rc;
/* register 'device' debug area, used for all DBF_DEV_XXX calls */
- device->debug_area = debug_register(device->cdev->dev.bus_id, 0, 2,
+ device->debug_area = debug_register(device->cdev->dev.bus_id, 1, 2,
8 * sizeof (long));
debug_register_view(device->debug_area, &debug_sprintf_view);
debug_set_level(device->debug_area, DBF_EMERG);
@@ -1740,6 +1740,10 @@ dasd_exit(void)
dasd_proc_exit();
#endif
dasd_ioctl_exit();
+ if (dasd_page_cache != NULL) {
+ kmem_cache_destroy(dasd_page_cache);
+ dasd_page_cache = NULL;
+ }
dasd_gendisk_exit();
dasd_devmap_exit();
devfs_remove("dasd");
@@ -1952,26 +1956,24 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
* Automatically online either all dasd devices (dasd_autodetect) or
* all devices specified with dasd= parameters.
*/
+static int
+__dasd_auto_online(struct device *dev, void *data)
+{
+ struct ccw_device *cdev;
+
+ cdev = to_ccwdev(dev);
+ if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0)
+ ccw_device_set_online(cdev);
+ return 0;
+}
+
void
dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver)
{
struct device_driver *drv;
- struct device *d, *dev;
- struct ccw_device *cdev;
drv = get_driver(&dasd_discipline_driver->driver);
- down_read(&drv->bus->subsys.rwsem);
- dev = NULL;
- list_for_each_entry(d, &drv->devices, driver_list) {
- dev = get_device(d);
- if (!dev)
- continue;
- cdev = to_ccwdev(dev);
- if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0)
- ccw_device_set_online(cdev);
- put_device(dev);
- }
- up_read(&drv->bus->subsys.rwsem);
+ driver_for_each_device(drv, NULL, NULL, __dasd_auto_online);
put_driver(drv);
}
@@ -1983,7 +1985,7 @@ dasd_init(void)
init_waitqueue_head(&dasd_init_waitq);
/* register 'common' DASD debug area, used for all DBF_XXX calls */
- dasd_debug_area = debug_register("dasd", 0, 2, 8 * sizeof (long));
+ dasd_debug_area = debug_register("dasd", 1, 2, 8 * sizeof (long));
if (dasd_debug_area == NULL) {
rc = -ENOMEM;
goto failed;
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 7963ae343ee..28cb4613b7f 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -4,7 +4,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.39 $
+ * $Revision: 1.40 $
*/
#include <linux/config.h>
@@ -354,6 +354,8 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
}
cqr->device = device;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */
+ cqr->retries = 32;
+ cqr->buildclk = get_clock();
cqr->status = DASD_CQR_FILLED;
return cqr;
}
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index d7f19745911..43c34f8c5e6 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -9,13 +9,14 @@
*
* /proc interface for the dasd driver.
*
- * $Revision: 1.31 $
+ * $Revision: 1.32 $
*/
#include <linux/config.h>
#include <linux/ctype.h>
#include <linux/seq_file.h>
#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
#include <asm/debug.h>
#include <asm/uaccess.h>
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 16ab8d363ac..4fde4118899 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -35,14 +35,17 @@
static int dcssblk_open(struct inode *inode, struct file *filp);
static int dcssblk_release(struct inode *inode, struct file *filp);
static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
+static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
+ unsigned long *data);
static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
static int dcssblk_major;
static struct block_device_operations dcssblk_devops = {
- .owner = THIS_MODULE,
- .open = dcssblk_open,
- .release = dcssblk_release,
+ .owner = THIS_MODULE,
+ .open = dcssblk_open,
+ .release = dcssblk_release,
+ .direct_access = dcssblk_direct_access,
};
static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf,
@@ -641,6 +644,20 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio)
/* Request beyond end of DCSS segment. */
goto fail;
}
+ /* verify data transfer direction */
+ if (dev_info->is_shared) {
+ switch (dev_info->segment_type) {
+ case SEG_TYPE_SR:
+ case SEG_TYPE_ER:
+ case SEG_TYPE_SC:
+ /* cannot write to these segments */
+ if (bio_data_dir(bio) == WRITE) {
+ PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id);
+ goto fail;
+ }
+ }
+ }
+
index = (bio->bi_sector >> 3);
bio_for_each_segment(bvec, bio, i) {
page_addr = (unsigned long)
@@ -661,7 +678,26 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio)
bio_endio(bio, bytes_done, 0);
return 0;
fail:
- bio_io_error(bio, bytes_done);
+ bio_io_error(bio, bio->bi_size);
+ return 0;
+}
+
+static int
+dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
+ unsigned long *data)
+{
+ struct dcssblk_dev_info *dev_info;
+ unsigned long pgoff;
+
+ dev_info = bdev->bd_disk->private_data;
+ if (!dev_info)
+ return -ENODEV;
+ if (secnum % (PAGE_SIZE/512))
+ return -EINVAL;
+ pgoff = secnum / (PAGE_SIZE / 512);
+ if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start)
+ return -ERANGE;
+ *data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE);
return 0;
}
@@ -682,7 +718,7 @@ dcssblk_check_params(void)
buf[j-i] = dcssblk_segments[j];
}
buf[j-i] = '\0';
- rc = dcssblk_add_store(dcssblk_root_dev, buf, j-i);
+ rc = dcssblk_add_store(dcssblk_root_dev, NULL, buf, j-i);
if ((rc >= 0) && (dcssblk_segments[j] == '(')) {
for (k = 0; buf[k] != '\0'; k++)
buf[k] = toupper(buf[k]);
@@ -692,7 +728,7 @@ dcssblk_check_params(void)
up_read(&dcssblk_devices_sem);
if (dev_info)
dcssblk_shared_store(&dev_info->dev,
- "0\n", 2);
+ NULL, "0\n", 2);
}
}
while ((dcssblk_segments[j] != ',') &&
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index 14e8cce9f86..6377a96735d 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o
obj-$(CONFIG_ZVM_WATCHDOG) += vmwatchdog.o
obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o
+obj-$(CONFIG_VMCP) += vmcp.o
tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o
tape-$(CONFIG_PROC_FS) += tape_proc.o
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 022f17bff73..f11a67fda40 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -860,8 +860,8 @@ con3215_init(void)
/* Set the console mode for VM */
if (MACHINE_IS_VM) {
- cpcmd("TERM CONMODE 3215", NULL, 0);
- cpcmd("TERM AUTOCR OFF", NULL, 0);
+ cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
+ cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
}
/* allocate 3215 request structures */
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index d52fb57a6b1..fc7a213e591 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -591,8 +591,8 @@ con3270_init(void)
/* Set the console mode for VM */
if (MACHINE_IS_VM) {
- cpcmd("TERM CONMODE 3270", 0, 0);
- cpcmd("TERM AUTOCR OFF", 0, 0);
+ cpcmd("TERM CONMODE 3270", NULL, 0, NULL);
+ cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
}
cdev = ccw_device_probe_console();
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index d04e6c2c3cc..01d865d9379 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -3,10 +3,11 @@
* tape device driver for 3480/3490E/3590 tapes.
*
* S390 and zSeries version
- * Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Carsten Otte <cotte@de.ibm.com>
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
+ * Stefan Bader <shbader@de.ibm.com>
*/
#ifndef _TAPE_H
@@ -111,6 +112,7 @@ enum tape_request_status {
TAPE_REQUEST_QUEUED, /* request is queued to be processed */
TAPE_REQUEST_IN_IO, /* request is currently in IO */
TAPE_REQUEST_DONE, /* request is completed. */
+ TAPE_REQUEST_CANCEL, /* request should be canceled. */
};
/* Tape CCW request */
@@ -237,6 +239,9 @@ struct tape_device {
/* Block dev frontend data */
struct tape_blk_data blk_data;
#endif
+
+ /* Function to start or stop the next request later. */
+ struct work_struct tape_dnr;
};
/* Externals from tape_core.c */
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 480ec87976f..20be88e91fa 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1351,13 +1351,13 @@ tape_34xx_init (void)
{
int rc;
- TAPE_DBF_AREA = debug_register ( "tape_34xx", 1, 2, 4*sizeof(long));
+ TAPE_DBF_AREA = debug_register ( "tape_34xx", 2, 2, 4*sizeof(long));
debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view);
#ifdef DBF_LIKE_HELL
debug_set_level(TAPE_DBF_AREA, 6);
#endif
- DBF_EVENT(3, "34xx init: $Revision: 1.21 $\n");
+ DBF_EVENT(3, "34xx init: $Revision: 1.23 $\n");
/* Register driver for 3480/3490 tapes. */
rc = ccw_driver_register(&tape_34xx_driver);
if (rc)
@@ -1378,7 +1378,7 @@ tape_34xx_exit(void)
MODULE_DEVICE_TABLE(ccw, tape_34xx_ids);
MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH");
MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape "
- "device driver ($Revision: 1.21 $)");
+ "device driver ($Revision: 1.23 $)");
MODULE_LICENSE("GPL");
module_init(tape_34xx_init);
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index b4df4a515b1..6c52e8307dc 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -3,11 +3,12 @@
* basic function of the tape device driver
*
* S390 and zSeries version
- * Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Carsten Otte <cotte@de.ibm.com>
* Michael Holzheu <holzheu@de.ibm.com>
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
+ * Stefan Bader <shbader@de.ibm.com>
*/
#include <linux/config.h>
@@ -28,7 +29,7 @@
#define PRINTK_HEADER "TAPE_CORE: "
static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *);
-static void __tape_remove_request(struct tape_device *, struct tape_request *);
+static void tape_delayed_next_request(void * data);
/*
* One list to contain all tape devices of all disciplines, so
@@ -257,7 +258,7 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate)
* Stop running ccw. Has to be called with the device lock held.
*/
static inline int
-__tape_halt_io(struct tape_device *device, struct tape_request *request)
+__tape_cancel_io(struct tape_device *device, struct tape_request *request)
{
int retries;
int rc;
@@ -270,20 +271,23 @@ __tape_halt_io(struct tape_device *device, struct tape_request *request)
for (retries = 0; retries < 5; retries++) {
rc = ccw_device_clear(device->cdev, (long) request);
- if (rc == 0) { /* Termination successful */
- request->rc = -EIO;
- request->status = TAPE_REQUEST_DONE;
- return 0;
+ switch (rc) {
+ case 0:
+ request->status = TAPE_REQUEST_DONE;
+ return 0;
+ case -EBUSY:
+ request->status = TAPE_REQUEST_CANCEL;
+ schedule_work(&device->tape_dnr);
+ return 0;
+ case -ENODEV:
+ DBF_EXCEPTION(2, "device gone, retry\n");
+ break;
+ case -EIO:
+ DBF_EXCEPTION(2, "I/O error, retry\n");
+ break;
+ default:
+ BUG();
}
-
- if (rc == -ENODEV)
- DBF_EXCEPTION(2, "device gone, retry\n");
- else if (rc == -EIO)
- DBF_EXCEPTION(2, "I/O error, retry\n");
- else if (rc == -EBUSY)
- DBF_EXCEPTION(2, "device busy, retry late\n");
- else
- BUG();
}
return rc;
@@ -473,6 +477,7 @@ tape_alloc_device(void)
*device->modeset_byte = 0;
device->first_minor = -1;
atomic_set(&device->ref_count, 1);
+ INIT_WORK(&device->tape_dnr, tape_delayed_next_request, device);
return device;
}
@@ -708,54 +713,119 @@ tape_free_request (struct tape_request * request)
kfree(request);
}
+static inline int
+__tape_start_io(struct tape_device *device, struct tape_request *request)
+{
+ int rc;
+
+#ifdef CONFIG_S390_TAPE_BLOCK
+ if (request->op == TO_BLOCK)
+ device->discipline->check_locate(device, request);
+#endif
+ rc = ccw_device_start(
+ device->cdev,
+ request->cpaddr,
+ (unsigned long) request,
+ 0x00,
+ request->options
+ );
+ if (rc == 0) {
+ request->status = TAPE_REQUEST_IN_IO;
+ } else if (rc == -EBUSY) {
+ /* The common I/O subsystem is currently busy. Retry later. */
+ request->status = TAPE_REQUEST_QUEUED;
+ schedule_work(&device->tape_dnr);
+ rc = 0;
+ } else {
+ /* Start failed. Remove request and indicate failure. */
+ DBF_EVENT(1, "tape: start request failed with RC = %i\n", rc);
+ }
+ return rc;
+}
+
static inline void
-__tape_do_io_list(struct tape_device *device)
+__tape_start_next_request(struct tape_device *device)
{
struct list_head *l, *n;
struct tape_request *request;
int rc;
- DBF_LH(6, "__tape_do_io_list(%p)\n", device);
+ DBF_LH(6, "__tape_start_next_request(%p)\n", device);
/*
* Try to start each request on request queue until one is
* started successful.
*/
list_for_each_safe(l, n, &device->req_queue) {
request = list_entry(l, struct tape_request, list);
-#ifdef CONFIG_S390_TAPE_BLOCK
- if (request->op == TO_BLOCK)
- device->discipline->check_locate(device, request);
-#endif
- rc = ccw_device_start(device->cdev, request->cpaddr,
- (unsigned long) request, 0x00,
- request->options);
- if (rc == 0) {
- request->status = TAPE_REQUEST_IN_IO;
- break;
+
+ /*
+ * Avoid race condition if bottom-half was triggered more than
+ * once.
+ */
+ if (request->status == TAPE_REQUEST_IN_IO)
+ return;
+
+ /*
+ * We wanted to cancel the request but the common I/O layer
+ * was busy at that time. This can only happen if this
+ * function is called by delayed_next_request.
+ * Otherwise we start the next request on the queue.
+ */
+ if (request->status == TAPE_REQUEST_CANCEL) {
+ rc = __tape_cancel_io(device, request);
+ } else {
+ rc = __tape_start_io(device, request);
}
- /* Start failed. Remove request and indicate failure. */
- DBF_EVENT(1, "tape: DOIO failed with er = %i\n", rc);
+ if (rc == 0)
+ return;
- /* Set ending status and do callback. */
+ /* Set ending status. */
request->rc = rc;
request->status = TAPE_REQUEST_DONE;
- __tape_remove_request(device, request);
+
+ /* Remove from request queue. */
+ list_del(&request->list);
+
+ /* Do callback. */
+ if (request->callback != NULL)
+ request->callback(request, request->callback_data);
}
}
static void
-__tape_remove_request(struct tape_device *device, struct tape_request *request)
+tape_delayed_next_request(void *data)
{
- /* Remove from request queue. */
- list_del(&request->list);
+ struct tape_device * device;
- /* Do callback. */
- if (request->callback != NULL)
- request->callback(request, request->callback_data);
+ device = (struct tape_device *) data;
+ DBF_LH(6, "tape_delayed_next_request(%p)\n", device);
+ spin_lock_irq(get_ccwdev_lock(device->cdev));
+ __tape_start_next_request(device);
+ spin_unlock_irq(get_ccwdev_lock(device->cdev));
+}
+
+static inline void
+__tape_end_request(
+ struct tape_device * device,
+ struct tape_request * request,
+ int rc)
+{
+ DBF_LH(6, "__tape_end_request(%p, %p, %i)\n", device, request, rc);
+ if (request) {
+ request->rc = rc;
+ request->status = TAPE_REQUEST_DONE;
+
+ /* Remove from request queue. */
+ list_del(&request->list);
+
+ /* Do callback. */
+ if (request->callback != NULL)
+ request->callback(request, request->callback_data);
+ }
/* Start next request. */
if (!list_empty(&device->req_queue))
- __tape_do_io_list(device);
+ __tape_start_next_request(device);
}
/*
@@ -812,7 +882,7 @@ tape_dump_sense_dbf(struct tape_device *device, struct tape_request *request,
* the device lock held.
*/
static inline int
-__tape_do_io(struct tape_device *device, struct tape_request *request)
+__tape_start_request(struct tape_device *device, struct tape_request *request)
{
int rc;
@@ -837,24 +907,16 @@ __tape_do_io(struct tape_device *device, struct tape_request *request)
if (list_empty(&device->req_queue)) {
/* No other requests are on the queue. Start this one. */
-#ifdef CONFIG_S390_TAPE_BLOCK
- if (request->op == TO_BLOCK)
- device->discipline->check_locate(device, request);
-#endif
- rc = ccw_device_start(device->cdev, request->cpaddr,
- (unsigned long) request, 0x00,
- request->options);
- if (rc) {
- DBF_EVENT(1, "tape: DOIO failed with rc = %i\n", rc);
+ rc = __tape_start_io(device, request);
+ if (rc)
return rc;
- }
+
DBF_LH(5, "Request %p added for execution.\n", request);
list_add(&request->list, &device->req_queue);
- request->status = TAPE_REQUEST_IN_IO;
} else {
DBF_LH(5, "Request %p add to queue.\n", request);
- list_add_tail(&request->list, &device->req_queue);
request->status = TAPE_REQUEST_QUEUED;
+ list_add_tail(&request->list, &device->req_queue);
}
return 0;
}
@@ -872,7 +934,7 @@ tape_do_io_async(struct tape_device *device, struct tape_request *request)
spin_lock_irq(get_ccwdev_lock(device->cdev));
/* Add request to request queue and try to start it. */
- rc = __tape_do_io(device, request);
+ rc = __tape_start_request(device, request);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
return rc;
}
@@ -901,7 +963,7 @@ tape_do_io(struct tape_device *device, struct tape_request *request)
request->callback = __tape_wake_up;
request->callback_data = &wq;
/* Add request to request queue and try to start it. */
- rc = __tape_do_io(device, request);
+ rc = __tape_start_request(device, request);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
if (rc)
return rc;
@@ -935,7 +997,7 @@ tape_do_io_interruptible(struct tape_device *device,
/* Setup callback */
request->callback = __tape_wake_up_interruptible;
request->callback_data = &wq;
- rc = __tape_do_io(device, request);
+ rc = __tape_start_request(device, request);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
if (rc)
return rc;
@@ -944,36 +1006,27 @@ tape_do_io_interruptible(struct tape_device *device,
if (rc != -ERESTARTSYS)
/* Request finished normally. */
return request->rc;
+
/* Interrupted by a signal. We have to stop the current request. */
spin_lock_irq(get_ccwdev_lock(device->cdev));
- rc = __tape_halt_io(device, request);
+ rc = __tape_cancel_io(device, request);
+ spin_unlock_irq(get_ccwdev_lock(device->cdev));
if (rc == 0) {
+ /* Wait for the interrupt that acknowledges the halt. */
+ do {
+ rc = wait_event_interruptible(
+ wq,
+ (request->callback == NULL)
+ );
+ } while (rc != -ERESTARTSYS);
+
DBF_EVENT(3, "IO stopped on %08x\n", device->cdev_id);
rc = -ERESTARTSYS;
}
- spin_unlock_irq(get_ccwdev_lock(device->cdev));
return rc;
}
/*
- * Handle requests that return an i/o error in the irb.
- */
-static inline void
-tape_handle_killed_request(
- struct tape_device *device,
- struct tape_request *request)
-{
- if(request != NULL) {
- /* Set ending status. FIXME: Should the request be retried? */
- request->rc = -EIO;
- request->status = TAPE_REQUEST_DONE;
- __tape_remove_request(device, request);
- } else {
- __tape_do_io_list(device);
- }
-}
-
-/*
* Tape interrupt routine, called from the ccw_device layer
*/
static void
@@ -981,7 +1034,6 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
{
struct tape_device *device;
struct tape_request *request;
- int final;
int rc;
device = (struct tape_device *) cdev->dev.driver_data;
@@ -996,12 +1048,13 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
/* On special conditions irb is an error pointer */
if (IS_ERR(irb)) {
+ /* FIXME: What to do with the request? */
switch (PTR_ERR(irb)) {
case -ETIMEDOUT:
PRINT_WARN("(%s): Request timed out\n",
cdev->dev.bus_id);
case -EIO:
- tape_handle_killed_request(device, request);
+ __tape_end_request(device, request, -EIO);
break;
default:
PRINT_ERR("(%s): Unexpected i/o error %li\n",
@@ -1011,6 +1064,21 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
return;
}
+ /*
+ * If the condition code is not zero and the start function bit is
+ * still set, this is an deferred error and the last start I/O did
+ * not succeed. Restart the request now.
+ */
+ if (irb->scsw.cc != 0 && (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
+ PRINT_WARN("(%s): deferred cc=%i. restaring\n",
+ cdev->dev.bus_id,
+ irb->scsw.cc);
+ rc = __tape_start_io(device, request);
+ if (rc)
+ __tape_end_request(device, request, rc);
+ return;
+ }
+
/* May be an unsolicited irq */
if(request != NULL)
request->rescnt = irb->scsw.count;
@@ -1042,7 +1110,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
* To detect these request the state will be set to TAPE_REQUEST_DONE.
*/
if(request != NULL && request->status == TAPE_REQUEST_DONE) {
- __tape_remove_request(device, request);
+ __tape_end_request(device, request, -EIO);
return;
}
@@ -1054,51 +1122,34 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
* rc == TAPE_IO_RETRY: request finished but needs another go.
* rc == TAPE_IO_STOP: request needs to get terminated.
*/
- final = 0;
switch (rc) {
- case TAPE_IO_SUCCESS:
- /* Upon normal completion the device _is_ online */
- device->tape_generic_status |= GMT_ONLINE(~0);
- final = 1;
- break;
- case TAPE_IO_PENDING:
- break;
- case TAPE_IO_RETRY:
-#ifdef CONFIG_S390_TAPE_BLOCK
- if (request->op == TO_BLOCK)
- device->discipline->check_locate(device, request);
-#endif
- rc = ccw_device_start(cdev, request->cpaddr,
- (unsigned long) request, 0x00,
- request->options);
- if (rc) {
- DBF_EVENT(1, "tape: DOIO failed with er = %i\n", rc);
- final = 1;
- }
- break;
- case TAPE_IO_STOP:
- __tape_halt_io(device, request);
- break;
- default:
- if (rc > 0) {
- DBF_EVENT(6, "xunknownrc\n");
- PRINT_ERR("Invalid return code from discipline "
- "interrupt function.\n");
- rc = -EIO;
- }
- final = 1;
- break;
- }
- if (final) {
- /* May be an unsolicited irq */
- if(request != NULL) {
- /* Set ending status. */
- request->rc = rc;
- request->status = TAPE_REQUEST_DONE;
- __tape_remove_request(device, request);
- } else {
- __tape_do_io_list(device);
- }
+ case TAPE_IO_SUCCESS:
+ /* Upon normal completion the device _is_ online */
+ device->tape_generic_status |= GMT_ONLINE(~0);
+ __tape_end_request(device, request, rc);
+ break;
+ case TAPE_IO_PENDING:
+ break;
+ case TAPE_IO_RETRY:
+ rc = __tape_start_io(device, request);
+ if (rc)
+ __tape_end_request(device, request, rc);
+ break;
+ case TAPE_IO_STOP:
+ rc = __tape_cancel_io(device, request);
+ if (rc)
+ __tape_end_request(device, request, rc);
+ break;
+ default:
+ if (rc > 0) {
+ DBF_EVENT(6, "xunknownrc\n");
+ PRINT_ERR("Invalid return code from discipline "
+ "interrupt function.\n");
+ __tape_end_request(device, request, -EIO);
+ } else {
+ __tape_end_request(device, request, rc);
+ }
+ break;
}
}
@@ -1186,12 +1237,12 @@ tape_mtop(struct tape_device *device, int mt_op, int mt_count)
static int
tape_init (void)
{
- TAPE_DBF_AREA = debug_register ( "tape", 1, 2, 4*sizeof(long));
+ TAPE_DBF_AREA = debug_register ( "tape", 2, 2, 4*sizeof(long));
debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view);
#ifdef DBF_LIKE_HELL
debug_set_level(TAPE_DBF_AREA, 6);
#endif
- DBF_EVENT(3, "tape init: ($Revision: 1.51 $)\n");
+ DBF_EVENT(3, "tape init: ($Revision: 1.54 $)\n");
tape_proc_init();
tapechar_init ();
tapeblock_init ();
@@ -1216,7 +1267,7 @@ tape_exit(void)
MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and "
"Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)");
MODULE_DESCRIPTION("Linux on zSeries channel attached "
- "tape device driver ($Revision: 1.51 $)");
+ "tape device driver ($Revision: 1.54 $)");
MODULE_LICENSE("GPL");
module_init(tape_init);
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index 801d17cca34..5fec0a10cc3 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
#define TAPE_DBF_AREA tape_core_dbf
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
new file mode 100644
index 00000000000..8990d8076e7
--- /dev/null
+++ b/drivers/s390/char/vmcp.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2004,2005 IBM Corporation
+ * Interface implementation for communication with the v/VM control program
+ * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
+ *
+ *
+ * z/VMs CP offers the possibility to issue commands via the diagnose code 8
+ * this driver implements a character device that issues these commands and
+ * returns the answer of CP.
+
+ * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <asm/cpcmd.h>
+#include <asm/debug.h>
+#include <asm/uaccess.h>
+#include "vmcp.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Borntraeger <cborntra@de.ibm.com>");
+MODULE_DESCRIPTION("z/VM CP interface");
+
+static debug_info_t *vmcp_debug;
+
+static int vmcp_open(struct inode *inode, struct file *file)
+{
+ struct vmcp_session *session;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ session = kmalloc(sizeof(*session), GFP_KERNEL);
+ if (!session)
+ return -ENOMEM;
+ session->bufsize = PAGE_SIZE;
+ session->response = NULL;
+ session->resp_size = 0;
+ init_MUTEX(&session->mutex);
+ file->private_data = session;
+ return nonseekable_open(inode, file);
+}
+
+static int vmcp_release(struct inode *inode, struct file *file)
+{
+ struct vmcp_session *session;
+
+ session = (struct vmcp_session *)file->private_data;
+ file->private_data = NULL;
+ free_pages((unsigned long)session->response, get_order(session->bufsize));
+ kfree(session);
+ return 0;
+}
+
+static ssize_t
+vmcp_read(struct file *file, char __user * buff, size_t count, loff_t * ppos)
+{
+ size_t tocopy;
+ struct vmcp_session *session;
+
+ session = (struct vmcp_session *)file->private_data;
+ if (down_interruptible(&session->mutex))
+ return -ERESTARTSYS;
+ if (!session->response) {
+ up(&session->mutex);
+ return 0;
+ }
+ if (*ppos > session->resp_size) {
+ up(&session->mutex);
+ return 0;
+ }
+ tocopy = min(session->resp_size - (size_t) (*ppos), count);
+ tocopy = min(tocopy,session->bufsize - (size_t) (*ppos));
+
+ if (copy_to_user(buff, session->response + (*ppos), tocopy)) {
+ up(&session->mutex);
+ return -EFAULT;
+ }
+ up(&session->mutex);
+ *ppos += tocopy;
+ return tocopy;
+}
+
+static ssize_t
+vmcp_write(struct file *file, const char __user * buff, size_t count,
+ loff_t * ppos)
+{
+ char *cmd;
+ struct vmcp_session *session;
+
+ if (count > 240)
+ return -EINVAL;
+ cmd = kmalloc(count + 1, GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+ if (copy_from_user(cmd, buff, count)) {
+ kfree(cmd);
+ return -EFAULT;
+ }
+ cmd[count] = '\0';
+ session = (struct vmcp_session *)file->private_data;
+ if (down_interruptible(&session->mutex))
+ return -ERESTARTSYS;
+ if (!session->response)
+ session->response = (char *)__get_free_pages(GFP_KERNEL
+ | __GFP_REPEAT | GFP_DMA,
+ get_order(session->bufsize));
+ if (!session->response) {
+ up(&session->mutex);
+ kfree(cmd);
+ return -ENOMEM;
+ }
+ debug_text_event(vmcp_debug, 1, cmd);
+ session->resp_size = __cpcmd(cmd, session->response,
+ session->bufsize,
+ &session->resp_code);
+ up(&session->mutex);
+ kfree(cmd);
+ *ppos = 0; /* reset the file pointer after a command */
+ return count;
+}
+
+
+/*
+ * These ioctls are available, as the semantics of the diagnose 8 call
+ * does not fit very well into a Linux call. Diagnose X'08' is described in
+ * CP Programming Services SC24-6084-00
+ *
+ * VMCP_GETCODE: gives the CP return code back to user space
+ * VMCP_SETBUF: sets the response buffer for the next write call. diagnose 8
+ * expects adjacent pages in real storage and to make matters worse, we
+ * dont know the size of the response. Therefore we default to PAGESIZE and
+ * let userspace to change the response size, if userspace expects a bigger
+ * response
+ */
+static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct vmcp_session *session;
+ int temp;
+
+ session = (struct vmcp_session *)file->private_data;
+ if (down_interruptible(&session->mutex))
+ return -ERESTARTSYS;
+ switch (cmd) {
+ case VMCP_GETCODE:
+ temp = session->resp_code;
+ up(&session->mutex);
+ return put_user(temp, (int __user *)arg);
+ case VMCP_SETBUF:
+ free_pages((unsigned long)session->response,
+ get_order(session->bufsize));
+ session->response=NULL;
+ temp = get_user(session->bufsize, (int __user *)arg);
+ if (get_order(session->bufsize) > 8) {
+ session->bufsize = PAGE_SIZE;
+ temp = -EINVAL;
+ }
+ up(&session->mutex);
+ return temp;
+ case VMCP_GETSIZE:
+ temp = session->resp_size;
+ up(&session->mutex);
+ return put_user(temp, (int __user *)arg);
+ default:
+ up(&session->mutex);
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct file_operations vmcp_fops = {
+ .owner = THIS_MODULE,
+ .open = &vmcp_open,
+ .release = &vmcp_release,
+ .read = &vmcp_read,
+ .llseek = &no_llseek,
+ .write = &vmcp_write,
+ .unlocked_ioctl = &vmcp_ioctl,
+ .compat_ioctl = &vmcp_ioctl
+};
+
+static struct miscdevice vmcp_dev = {
+ .name = "vmcp",
+ .minor = MISC_DYNAMIC_MINOR,
+ .fops = &vmcp_fops,
+};
+
+static int __init vmcp_init(void)
+{
+ int ret;
+
+ if (!MACHINE_IS_VM) {
+ printk(KERN_WARNING
+ "z/VM CP interface is only available under z/VM\n");
+ return -ENODEV;
+ }
+ ret = misc_register(&vmcp_dev);
+ if (!ret)
+ printk(KERN_INFO "z/VM CP interface loaded\n");
+ else
+ printk(KERN_WARNING
+ "z/VM CP interface not loaded. Could not register misc device.\n");
+ vmcp_debug = debug_register("vmcp", 1, 1, 240);
+ debug_register_view(vmcp_debug, &debug_hex_ascii_view);
+ return ret;
+}
+
+static void __exit vmcp_exit(void)
+{
+ WARN_ON(misc_deregister(&vmcp_dev) != 0);
+ debug_unregister(vmcp_debug);
+ printk(KERN_INFO "z/VM CP interface unloaded.\n");
+}
+
+module_init(vmcp_init);
+module_exit(vmcp_exit);
diff --git a/drivers/s390/char/vmcp.h b/drivers/s390/char/vmcp.h
new file mode 100644
index 00000000000..87389e73046
--- /dev/null
+++ b/drivers/s390/char/vmcp.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004, 2005 IBM Corporation
+ * Interface implementation for communication with the v/VM control program
+ * Version 1.0
+ * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
+ *
+ *
+ * z/VMs CP offers the possibility to issue commands via the diagnose code 8
+ * this driver implements a character device that issues these commands and
+ * returns the answer of CP.
+ *
+ * The idea of this driver is based on cpint from Neale Ferguson
+ */
+
+#include <asm/semaphore.h>
+#include <linux/ioctl.h>
+
+#define VMCP_GETCODE _IOR(0x10, 1, int)
+#define VMCP_SETBUF _IOW(0x10, 2, int)
+#define VMCP_GETSIZE _IOR(0x10, 3, int)
+
+struct vmcp_session {
+ unsigned int bufsize;
+ char *response;
+ int resp_size;
+ int resp_code;
+ /* As we use copy_from/to_user, which might *
+ * sleep and cannot use a spinlock */
+ struct semaphore mutex;
+};
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index f7717327d15..491f00c032e 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -236,7 +236,7 @@ vmlogrdr_get_recording_class_AB(void) {
int len,i;
printk (KERN_DEBUG "vmlogrdr: query command: %s\n", cp_command);
- cpcmd(cp_command, cp_response, sizeof(cp_response));
+ cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
printk (KERN_DEBUG "vmlogrdr: response: %s", cp_response);
len = strnlen(cp_response,sizeof(cp_response));
// now the parsing
@@ -288,7 +288,7 @@ vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
printk (KERN_DEBUG "vmlogrdr: recording command: %s\n",
cp_command);
- cpcmd(cp_command, cp_response, sizeof(cp_response));
+ cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
printk (KERN_DEBUG "vmlogrdr: recording response: %s",
cp_response);
}
@@ -301,7 +301,7 @@ vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
qid_string);
printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
- cpcmd(cp_command, cp_response, sizeof(cp_response));
+ cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
printk (KERN_DEBUG "vmlogrdr: recording response: %s",
cp_response);
/* The recording command will usually answer with 'Command complete'
@@ -607,7 +607,7 @@ vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const c
priv->recording_name);
printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
- cpcmd(cp_command, cp_response, sizeof(cp_response));
+ cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
printk (KERN_DEBUG "vmlogrdr: recording response: %s",
cp_response);
@@ -682,7 +682,7 @@ vmlogrdr_recording_status_show(struct device_driver *driver, char *buf) {
char cp_command[] = "QUERY RECORDING ";
int len;
- cpcmd(cp_command, buf, 4096);
+ cpcmd(cp_command, buf, 4096, NULL);
len = strlen(buf);
return len;
}
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 22cf4fec8da..5473c23fcb5 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -23,11 +23,7 @@
static char vmwdt_cmd[MAX_CMDLEN] = "IPL";
static int vmwdt_conceal;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-static int vmwdt_nowayout = 1;
-#else
-static int vmwdt_nowayout = 0;
-#endif
+static int vmwdt_nowayout = WATCHDOG_NOWAYOUT;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 306525acb9f..91ea8e4777f 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -403,34 +403,22 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
return driver_register(&cdriver->driver);
}
-static inline struct device *
-__get_next_ccwgroup_device(struct device_driver *drv)
+static int
+__ccwgroup_driver_unregister_device(struct device *dev, void *data)
{
- struct device *dev, *d;
-
- down_read(&drv->bus->subsys.rwsem);
- dev = NULL;
- list_for_each_entry(d, &drv->devices, driver_list) {
- dev = get_device(d);
- if (dev)
- break;
- }
- up_read(&drv->bus->subsys.rwsem);
- return dev;
+ __ccwgroup_remove_symlinks(to_ccwgroupdev(dev));
+ device_unregister(dev);
+ put_device(dev);
+ return 0;
}
void
ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver)
{
- struct device *dev;
-
/* We don't want ccwgroup devices to live longer than their driver. */
get_driver(&cdriver->driver);
- while ((dev = __get_next_ccwgroup_device(&cdriver->driver))) {
- __ccwgroup_remove_symlinks(to_ccwgroupdev(dev));
- device_unregister(dev);
- put_device(dev);
- };
+ driver_for_each_device(&cdriver->driver, NULL, NULL,
+ __ccwgroup_driver_unregister_device);
put_driver(&cdriver->driver);
driver_unregister(&cdriver->driver);
}
@@ -449,7 +437,7 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
if (cdev->dev.driver_data) {
gdev = (struct ccwgroup_device *)cdev->dev.driver_data;
if (get_device(&gdev->dev)) {
- if (!list_empty(&gdev->dev.node))
+ if (klist_node_attached(&gdev->dev.knode_bus))
return gdev;
put_device(&gdev->dev);
}
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index b86f94ecd87..fa3c23b80e3 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/chsc.c
* S/390 common I/O routines -- channel subsystem call
- * $Revision: 1.119 $
+ * $Revision: 1.120 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -412,11 +412,7 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
if (chp_mask == 0) {
spin_unlock_irq(&sch->lock);
-
- if (fla_mask != 0)
- break;
- else
- continue;
+ continue;
}
old_lpm = sch->lpm;
sch->lpm = ((sch->schib.pmcw.pim &
@@ -430,7 +426,7 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
spin_unlock_irq(&sch->lock);
put_device(&sch->dev);
- if (fla_mask != 0)
+ if (fla_mask == 0xffff)
break;
}
return rc;
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 1d9b3f18d8d..ea813bdce1d 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
- * $Revision: 1.133 $
+ * $Revision: 1.134 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -63,17 +63,17 @@ __setup ("cio_msg=", cio_setup);
static int __init
cio_debug_init (void)
{
- cio_debug_msg_id = debug_register ("cio_msg", 4, 4, 16*sizeof (long));
+ cio_debug_msg_id = debug_register ("cio_msg", 16, 4, 16*sizeof (long));
if (!cio_debug_msg_id)
goto out_unregister;
debug_register_view (cio_debug_msg_id, &debug_sprintf_view);
debug_set_level (cio_debug_msg_id, 2);
- cio_debug_trace_id = debug_register ("cio_trace", 4, 4, 8);
+ cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 8);
if (!cio_debug_trace_id)
goto out_unregister;
debug_register_view (cio_debug_trace_id, &debug_hex_ascii_view);
debug_set_level (cio_debug_trace_id, 2);
- cio_debug_crw_id = debug_register ("cio_crw", 2, 4, 16*sizeof (long));
+ cio_debug_crw_id = debug_register ("cio_crw", 4, 4, 16*sizeof (long));
if (!cio_debug_crw_id)
goto out_unregister;
debug_register_view (cio_debug_crw_id, &debug_sprintf_view);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 87bd70eeabe..555119cacc2 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -128,34 +128,28 @@ css_probe_device(int irq)
return ret;
}
+static int
+check_subchannel(struct device * dev, void * data)
+{
+ struct subchannel *sch;
+ int irq = (unsigned long)data;
+
+ sch = to_subchannel(dev);
+ return (sch->irq == irq);
+}
+
struct subchannel *
get_subchannel_by_schid(int irq)
{
- struct subchannel *sch;
- struct list_head *entry;
struct device *dev;
- if (!get_bus(&css_bus_type))
- return NULL;
- down_read(&css_bus_type.subsys.rwsem);
- sch = NULL;
- list_for_each(entry, &css_bus_type.devices.list) {
- dev = get_device(container_of(entry,
- struct device, bus_list));
- if (!dev)
- continue;
- sch = to_subchannel(dev);
- if (sch->irq == irq)
- break;
- put_device(dev);
- sch = NULL;
- }
- up_read(&css_bus_type.subsys.rwsem);
- put_bus(&css_bus_type);
+ dev = bus_find_device(&css_bus_type, NULL,
+ (void *)(unsigned long)irq, check_subchannel);
- return sch;
+ return dev ? to_subchannel(dev) : NULL;
}
+
static inline int
css_get_subchannel_status(struct subchannel *sch, int schid)
{
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 809e1108a06..14c76f5e417 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -514,36 +514,39 @@ ccw_device_register(struct ccw_device *cdev)
return ret;
}
+struct match_data {
+ unsigned int devno;
+ struct ccw_device * sibling;
+};
+
+static int
+match_devno(struct device * dev, void * data)
+{
+ struct match_data * d = (struct match_data *)data;
+ struct ccw_device * cdev;
+
+ cdev = to_ccwdev(dev);
+ if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
+ (cdev->private->devno == d->devno) &&
+ (cdev != d->sibling)) {
+ cdev->private->state = DEV_STATE_NOT_OPER;
+ return 1;
+ }
+ return 0;
+}
+
static struct ccw_device *
get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
{
- struct ccw_device *cdev;
- struct list_head *entry;
struct device *dev;
+ struct match_data data = {
+ .devno = devno,
+ .sibling = sibling,
+ };
- if (!get_bus(&ccw_bus_type))
- return NULL;
- down_read(&ccw_bus_type.subsys.rwsem);
- cdev = NULL;
- list_for_each(entry, &ccw_bus_type.devices.list) {
- dev = get_device(container_of(entry,
- struct device, bus_list));
- if (!dev)
- continue;
- cdev = to_ccwdev(dev);
- if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
- (cdev->private->devno == devno) &&
- (cdev != sibling)) {
- cdev->private->state = DEV_STATE_NOT_OPER;
- break;
- }
- put_device(dev);
- cdev = NULL;
- }
- up_read(&ccw_bus_type.subsys.rwsem);
- put_bus(&ccw_bus_type);
+ dev = bus_find_device(&css_bus_type, NULL, &data, match_devno);
- return cdev;
+ return dev ? to_ccwdev(dev) : NULL;
}
static void
@@ -647,7 +650,7 @@ io_subchannel_register(void *data)
cdev = (struct ccw_device *) data;
sch = to_subchannel(cdev->dev.parent);
- if (!list_empty(&sch->dev.children)) {
+ if (klist_node_attached(&cdev->dev.knode_parent)) {
bus_rescan_devices(&ccw_bus_type);
goto out;
}
@@ -1019,30 +1022,29 @@ ccw_device_probe_console(void)
/*
* get ccw_device matching the busid, but only if owned by cdrv
*/
+static int
+__ccwdev_check_busid(struct device *dev, void *id)
+{
+ char *bus_id;
+
+ bus_id = (char *)id;
+
+ return (strncmp(bus_id, dev->bus_id, BUS_ID_SIZE) == 0);
+}
+
+
struct ccw_device *
get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id)
{
- struct device *d, *dev;
+ struct device *dev;
struct device_driver *drv;
drv = get_driver(&cdrv->driver);
if (!drv)
- return 0;
-
- down_read(&drv->bus->subsys.rwsem);
-
- dev = NULL;
- list_for_each_entry(d, &drv->devices, driver_list) {
- dev = get_device(d);
+ return NULL;
- if (dev && !strncmp(bus_id, dev->bus_id, BUS_ID_SIZE))
- break;
- else if (dev) {
- put_device(dev);
- dev = NULL;
- }
- }
- up_read(&drv->bus->subsys.rwsem);
+ dev = driver_find_device(drv, NULL, (void *)bus_id,
+ __ccwdev_check_busid);
put_driver(drv);
return dev ? to_ccwdev(dev) : 0;
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 9b7f6f548b1..ee7a05e0c3b 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -235,6 +235,9 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
sch->schib.pmcw.pam &
sch->schib.pmcw.pom &
sch->opm;
+ /* Check since device may again have become not operational. */
+ if (!sch->schib.pmcw.dnv)
+ state = DEV_STATE_NOT_OPER;
if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID)
/* Force reprobe on all chpids. */
old_lpm = 0;
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 4ab2e0d9500..12a24d4331a 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -39,15 +39,14 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
" ... device %04X on subchannel %04X, dev_stat "
": %02X sch_stat : %02X\n",
cdev->private->devno, cdev->private->irq,
- cdev->private->irb.scsw.dstat,
- cdev->private->irb.scsw.cstat);
+ irb->scsw.dstat, irb->scsw.cstat);
if (irb->scsw.cc != 3) {
char dbf_text[15];
sprintf(dbf_text, "chk%x", cdev->private->irq);
CIO_TRACE_EVENT(0, dbf_text);
- CIO_HEX_EVENT(0, &cdev->private->irb, sizeof (struct irb));
+ CIO_HEX_EVENT(0, irb, sizeof (struct irb));
}
}
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index bbe9f45d143..381f339e320 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,7 +56,7 @@
#include "ioasm.h"
#include "chsc.h"
-#define VERSION_QDIO_C "$Revision: 1.98 $"
+#define VERSION_QDIO_C "$Revision: 1.101 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -112,7 +112,7 @@ qdio_min(int a,int b)
/***************** SCRUBBER HELPER ROUTINES **********************/
-static inline volatile __u64
+static inline __u64
qdio_get_micros(void)
{
return (get_clock() >> 10); /* time>>12 is microseconds */
@@ -230,7 +230,7 @@ qdio_siga_input(struct qdio_q *q)
}
/* locked by the locks in qdio_activate and qdio_cleanup */
-static __u32 * volatile
+static __u32 volatile *
qdio_get_indicator(void)
{
int i;
@@ -432,7 +432,7 @@ tiqdio_clear_global_summary(void)
/************************* OUTBOUND ROUTINES *******************************/
-inline static int
+static inline int
qdio_get_outbound_buffer_frontier(struct qdio_q *q)
{
int f,f_mod_no;
@@ -510,7 +510,7 @@ out:
}
/* all buffers are processed */
-inline static int
+static inline int
qdio_is_outbound_q_done(struct qdio_q *q)
{
int no_used;
@@ -532,7 +532,7 @@ qdio_is_outbound_q_done(struct qdio_q *q)
return (no_used==0);
}
-inline static int
+static inline int
qdio_has_outbound_q_moved(struct qdio_q *q)
{
int i;
@@ -552,7 +552,7 @@ qdio_has_outbound_q_moved(struct qdio_q *q)
}
}
-inline static void
+static inline void
qdio_kick_outbound_q(struct qdio_q *q)
{
int result;
@@ -641,7 +641,7 @@ qdio_kick_outbound_q(struct qdio_q *q)
}
}
-inline static void
+static inline void
qdio_kick_outbound_handler(struct qdio_q *q)
{
int start, end, real_end, count;
@@ -740,7 +740,7 @@ qdio_outbound_processing(struct qdio_q *q)
/************************* INBOUND ROUTINES *******************************/
-inline static int
+static inline int
qdio_get_inbound_buffer_frontier(struct qdio_q *q)
{
int f,f_mod_no;
@@ -865,7 +865,7 @@ out:
return q->first_to_check;
}
-inline static int
+static inline int
qdio_has_inbound_q_moved(struct qdio_q *q)
{
int i;
@@ -898,7 +898,7 @@ qdio_has_inbound_q_moved(struct qdio_q *q)
}
/* means, no more buffers to be filled */
-inline static int
+static inline int
tiqdio_is_inbound_q_done(struct qdio_q *q)
{
int no_used;
@@ -951,7 +951,7 @@ tiqdio_is_inbound_q_done(struct qdio_q *q)
return 0;
}
-inline static int
+static inline int
qdio_is_inbound_q_done(struct qdio_q *q)
{
int no_used;
@@ -1010,7 +1010,7 @@ qdio_is_inbound_q_done(struct qdio_q *q)
}
}
-inline static void
+static inline void
qdio_kick_inbound_handler(struct qdio_q *q)
{
int count, start, end, real_end, i;
@@ -3342,7 +3342,7 @@ static int
qdio_register_dbf_views(void)
{
qdio_dbf_setup=debug_register(QDIO_DBF_SETUP_NAME,
- QDIO_DBF_SETUP_INDEX,
+ QDIO_DBF_SETUP_PAGES,
QDIO_DBF_SETUP_NR_AREAS,
QDIO_DBF_SETUP_LEN);
if (!qdio_dbf_setup)
@@ -3351,7 +3351,7 @@ qdio_register_dbf_views(void)
debug_set_level(qdio_dbf_setup,QDIO_DBF_SETUP_LEVEL);
qdio_dbf_sbal=debug_register(QDIO_DBF_SBAL_NAME,
- QDIO_DBF_SBAL_INDEX,
+ QDIO_DBF_SBAL_PAGES,
QDIO_DBF_SBAL_NR_AREAS,
QDIO_DBF_SBAL_LEN);
if (!qdio_dbf_sbal)
@@ -3361,7 +3361,7 @@ qdio_register_dbf_views(void)
debug_set_level(qdio_dbf_sbal,QDIO_DBF_SBAL_LEVEL);
qdio_dbf_sense=debug_register(QDIO_DBF_SENSE_NAME,
- QDIO_DBF_SENSE_INDEX,
+ QDIO_DBF_SENSE_PAGES,
QDIO_DBF_SENSE_NR_AREAS,
QDIO_DBF_SENSE_LEN);
if (!qdio_dbf_sense)
@@ -3371,7 +3371,7 @@ qdio_register_dbf_views(void)
debug_set_level(qdio_dbf_sense,QDIO_DBF_SENSE_LEVEL);
qdio_dbf_trace=debug_register(QDIO_DBF_TRACE_NAME,
- QDIO_DBF_TRACE_INDEX,
+ QDIO_DBF_TRACE_PAGES,
QDIO_DBF_TRACE_NR_AREAS,
QDIO_DBF_TRACE_LEN);
if (!qdio_dbf_trace)
@@ -3382,7 +3382,7 @@ qdio_register_dbf_views(void)
#ifdef CONFIG_QDIO_DEBUG
qdio_dbf_slsb_out=debug_register(QDIO_DBF_SLSB_OUT_NAME,
- QDIO_DBF_SLSB_OUT_INDEX,
+ QDIO_DBF_SLSB_OUT_PAGES,
QDIO_DBF_SLSB_OUT_NR_AREAS,
QDIO_DBF_SLSB_OUT_LEN);
if (!qdio_dbf_slsb_out)
@@ -3391,7 +3391,7 @@ qdio_register_dbf_views(void)
debug_set_level(qdio_dbf_slsb_out,QDIO_DBF_SLSB_OUT_LEVEL);
qdio_dbf_slsb_in=debug_register(QDIO_DBF_SLSB_IN_NAME,
- QDIO_DBF_SLSB_IN_INDEX,
+ QDIO_DBF_SLSB_IN_PAGES,
QDIO_DBF_SLSB_IN_NR_AREAS,
QDIO_DBF_SLSB_IN_LEN);
if (!qdio_dbf_slsb_in)
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index b6daadac4e8..6b8aa6a852b 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -3,7 +3,7 @@
#include <asm/page.h>
-#define VERSION_CIO_QDIO_H "$Revision: 1.32 $"
+#define VERSION_CIO_QDIO_H "$Revision: 1.33 $"
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_VERBOSE_LEVEL 9
@@ -132,7 +132,7 @@ enum qdio_irq_states {
#define QDIO_DBF_SETUP_NAME "qdio_setup"
#define QDIO_DBF_SETUP_LEN 8
-#define QDIO_DBF_SETUP_INDEX 2
+#define QDIO_DBF_SETUP_PAGES 4
#define QDIO_DBF_SETUP_NR_AREAS 1
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_DBF_SETUP_LEVEL 6
@@ -142,7 +142,7 @@ enum qdio_irq_states {
#define QDIO_DBF_SBAL_NAME "qdio_labs" /* sbal */
#define QDIO_DBF_SBAL_LEN 256
-#define QDIO_DBF_SBAL_INDEX 2
+#define QDIO_DBF_SBAL_PAGES 4
#define QDIO_DBF_SBAL_NR_AREAS 2
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_DBF_SBAL_LEVEL 6
@@ -154,16 +154,16 @@ enum qdio_irq_states {
#define QDIO_DBF_TRACE_LEN 8
#define QDIO_DBF_TRACE_NR_AREAS 2
#ifdef CONFIG_QDIO_DEBUG
-#define QDIO_DBF_TRACE_INDEX 4
+#define QDIO_DBF_TRACE_PAGES 16
#define QDIO_DBF_TRACE_LEVEL 4 /* -------- could be even more verbose here */
#else /* CONFIG_QDIO_DEBUG */
-#define QDIO_DBF_TRACE_INDEX 2
+#define QDIO_DBF_TRACE_PAGES 4
#define QDIO_DBF_TRACE_LEVEL 2
#endif /* CONFIG_QDIO_DEBUG */
#define QDIO_DBF_SENSE_NAME "qdio_sense"
#define QDIO_DBF_SENSE_LEN 64
-#define QDIO_DBF_SENSE_INDEX 1
+#define QDIO_DBF_SENSE_PAGES 2
#define QDIO_DBF_SENSE_NR_AREAS 1
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_DBF_SENSE_LEVEL 6
@@ -176,13 +176,13 @@ enum qdio_irq_states {
#define QDIO_DBF_SLSB_OUT_NAME "qdio_slsb_out"
#define QDIO_DBF_SLSB_OUT_LEN QDIO_MAX_BUFFERS_PER_Q
-#define QDIO_DBF_SLSB_OUT_INDEX 8
+#define QDIO_DBF_SLSB_OUT_PAGES 256
#define QDIO_DBF_SLSB_OUT_NR_AREAS 1
#define QDIO_DBF_SLSB_OUT_LEVEL 6
#define QDIO_DBF_SLSB_IN_NAME "qdio_slsb_in"
#define QDIO_DBF_SLSB_IN_LEN QDIO_MAX_BUFFERS_PER_Q
-#define QDIO_DBF_SLSB_IN_INDEX 8
+#define QDIO_DBF_SLSB_IN_PAGES 256
#define QDIO_DBF_SLSB_IN_NR_AREAS 1
#define QDIO_DBF_SLSB_IN_LEVEL 6
#endif /* CONFIG_QDIO_DEBUG */
diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h
index 82a1d97001d..0a3bb5a10dd 100644
--- a/drivers/s390/crypto/z90crypt.h
+++ b/drivers/s390/crypto/z90crypt.h
@@ -36,15 +36,6 @@
#define z90crypt_VARIANT 2 // 2 = added PCIXCC MCL3 and CEX2C support
/**
- * If we are not using the sparse checker, __user has no use.
- */
-#ifdef __CHECKER__
-# define __user __attribute__((noderef, address_space(1)))
-#else
-# define __user
-#endif
-
-/**
* struct ica_rsa_modexpo
*
* Requirements:
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index a99927d54eb..24c0af49c25 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -146,8 +146,8 @@ claw_unregister_debug_facility(void)
static int
claw_register_debug_facility(void)
{
- claw_dbf_setup = debug_register("claw_setup", 1, 1, 8);
- claw_dbf_trace = debug_register("claw_trace", 1, 2, 8);
+ claw_dbf_setup = debug_register("claw_setup", 2, 1, 8);
+ claw_dbf_trace = debug_register("claw_trace", 2, 2, 8);
if (claw_dbf_setup == NULL || claw_dbf_trace == NULL) {
printk(KERN_WARNING "Not enough memory for debug facility.\n");
claw_unregister_debug_facility();
@@ -428,7 +428,7 @@ claw_pack_skb(struct claw_privbk *privptr)
new_skb = NULL; /* assume no dice */
pkt_cnt = 0;
CLAW_DBF_TEXT(4,trace,"PackSKBe");
- if (skb_queue_len(&p_ch->collect_queue) > 0) {
+ if (!skb_queue_empty(&p_ch->collect_queue)) {
/* some data */
held_skb = skb_dequeue(&p_ch->collect_queue);
if (p_env->packing != DO_PACKED)
@@ -1254,7 +1254,7 @@ claw_write_next ( struct chbk * p_ch )
privptr = (struct claw_privbk *) dev->priv;
claw_free_wrt_buf( dev );
if ((privptr->write_free_count > 0) &&
- (skb_queue_len(&p_ch->collect_queue) > 0)) {
+ !skb_queue_empty(&p_ch->collect_queue)) {
pk_skb = claw_pack_skb(privptr);
while (pk_skb != NULL) {
rc = claw_hw_tx( pk_skb, dev,1);
diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c
index 2c86bfa11b2..0e2a8bb9303 100644
--- a/drivers/s390/net/ctcdbug.c
+++ b/drivers/s390/net/ctcdbug.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.4 $)
+ * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.6 $)
*
* CTC / ESCON network driver - s390 dbf exploit.
*
@@ -9,7 +9,7 @@
* Author(s): Original Code written by
* Peter Tiedemann (ptiedem@de.ibm.com)
*
- * $Revision: 1.4 $ $Date: 2004/08/04 10:11:59 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 08:10:17 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -51,15 +51,15 @@ int
ctc_register_dbf_views(void)
{
ctc_dbf_setup = debug_register(CTC_DBF_SETUP_NAME,
- CTC_DBF_SETUP_INDEX,
+ CTC_DBF_SETUP_PAGES,
CTC_DBF_SETUP_NR_AREAS,
CTC_DBF_SETUP_LEN);
ctc_dbf_data = debug_register(CTC_DBF_DATA_NAME,
- CTC_DBF_DATA_INDEX,
+ CTC_DBF_DATA_PAGES,
CTC_DBF_DATA_NR_AREAS,
CTC_DBF_DATA_LEN);
ctc_dbf_trace = debug_register(CTC_DBF_TRACE_NAME,
- CTC_DBF_TRACE_INDEX,
+ CTC_DBF_TRACE_PAGES,
CTC_DBF_TRACE_NR_AREAS,
CTC_DBF_TRACE_LEN);
diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
index 7fe2ebd1792..7d6afa1627c 100644
--- a/drivers/s390/net/ctcdbug.h
+++ b/drivers/s390/net/ctcdbug.h
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.5 $)
+ * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.6 $)
*
* CTC / ESCON network driver - s390 dbf exploit.
*
@@ -9,7 +9,7 @@
* Author(s): Original Code written by
* Peter Tiedemann (ptiedem@de.ibm.com)
*
- * $Revision: 1.5 $ $Date: 2005/02/27 19:46:44 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 08:10:17 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,19 +35,19 @@
*/
#define CTC_DBF_SETUP_NAME "ctc_setup"
#define CTC_DBF_SETUP_LEN 16
-#define CTC_DBF_SETUP_INDEX 3
+#define CTC_DBF_SETUP_PAGES 8
#define CTC_DBF_SETUP_NR_AREAS 1
#define CTC_DBF_SETUP_LEVEL 3
#define CTC_DBF_DATA_NAME "ctc_data"
#define CTC_DBF_DATA_LEN 128
-#define CTC_DBF_DATA_INDEX 3
+#define CTC_DBF_DATA_PAGES 8
#define CTC_DBF_DATA_NR_AREAS 1
#define CTC_DBF_DATA_LEVEL 3
#define CTC_DBF_TRACE_NAME "ctc_trace"
#define CTC_DBF_TRACE_LEN 16
-#define CTC_DBF_TRACE_INDEX 2
+#define CTC_DBF_TRACE_PAGES 4
#define CTC_DBF_TRACE_NR_AREAS 2
#define CTC_DBF_TRACE_LEVEL 3
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 3080393e823..968f2c113ef 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -156,7 +156,7 @@ ctc_tty_readmodem(ctc_tty_info *info)
skb_queue_head(&info->rx_queue, skb);
else {
kfree_skb(skb);
- ret = skb_queue_len(&info->rx_queue);
+ ret = !skb_queue_empty(&info->rx_queue);
}
}
}
@@ -530,7 +530,7 @@ ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count)
total += c;
count -= c;
}
- if (skb_queue_len(&info->tx_queue)) {
+ if (!skb_queue_empty(&info->tx_queue)) {
info->lsr &= ~UART_LSR_TEMT;
tasklet_schedule(&info->tasklet);
}
@@ -594,7 +594,7 @@ ctc_tty_flush_chars(struct tty_struct *tty)
return;
if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_chars"))
return;
- if (tty->stopped || tty->hw_stopped || (!skb_queue_len(&info->tx_queue)))
+ if (tty->stopped || tty->hw_stopped || skb_queue_empty(&info->tx_queue))
return;
tasklet_schedule(&info->tasklet);
}
diff --git a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h
index 198330217ef..0c4644d3d2f 100644
--- a/drivers/s390/net/iucv.h
+++ b/drivers/s390/net/iucv.h
@@ -37,19 +37,19 @@
*/
#define IUCV_DBF_SETUP_NAME "iucv_setup"
#define IUCV_DBF_SETUP_LEN 32
-#define IUCV_DBF_SETUP_INDEX 1
+#define IUCV_DBF_SETUP_PAGES 2
#define IUCV_DBF_SETUP_NR_AREAS 1
#define IUCV_DBF_SETUP_LEVEL 3
#define IUCV_DBF_DATA_NAME "iucv_data"
#define IUCV_DBF_DATA_LEN 128
-#define IUCV_DBF_DATA_INDEX 1
+#define IUCV_DBF_DATA_PAGES 2
#define IUCV_DBF_DATA_NR_AREAS 1
#define IUCV_DBF_DATA_LEVEL 2
#define IUCV_DBF_TRACE_NAME "iucv_trace"
#define IUCV_DBF_TRACE_LEN 16
-#define IUCV_DBF_TRACE_INDEX 2
+#define IUCV_DBF_TRACE_PAGES 4
#define IUCV_DBF_TRACE_NR_AREAS 1
#define IUCV_DBF_TRACE_LEVEL 3
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index ab086242d30..46f34ba93ac 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -11,7 +11,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*
- * $Revision: 1.98 $ $Date: 2005/04/18 13:41:29 $
+ * $Revision: 1.99 $ $Date: 2005/05/11 08:10:17 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -59,7 +59,7 @@
/**
* initialization string for output
*/
-#define VERSION_LCS_C "$Revision: 1.98 $"
+#define VERSION_LCS_C "$Revision: 1.99 $"
static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
static char debug_buffer[255];
@@ -93,8 +93,8 @@ lcs_unregister_debug_facility(void)
static int
lcs_register_debug_facility(void)
{
- lcs_dbf_setup = debug_register("lcs_setup", 1, 1, 8);
- lcs_dbf_trace = debug_register("lcs_trace", 1, 2, 8);
+ lcs_dbf_setup = debug_register("lcs_setup", 2, 1, 8);
+ lcs_dbf_trace = debug_register("lcs_trace", 2, 2, 8);
if (lcs_dbf_setup == NULL || lcs_dbf_trace == NULL) {
PRINT_ERR("Not enough memory for debug facility.\n");
lcs_unregister_debug_facility();
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 3fd4fb754b2..69425a7a6e9 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,5 +1,5 @@
/*
- * $Id: netiucv.c,v 1.63 2004/07/27 13:36:05 mschwide Exp $
+ * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $
*
* IUCV network driver
*
@@ -30,7 +30,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV network driver $Revision: 1.63 $
+ * RELEASE-TAG: IUCV network driver $Revision: 1.66 $
*
*/
@@ -391,15 +391,15 @@ static int
iucv_register_dbf_views(void)
{
iucv_dbf_setup = debug_register(IUCV_DBF_SETUP_NAME,
- IUCV_DBF_SETUP_INDEX,
+ IUCV_DBF_SETUP_PAGES,
IUCV_DBF_SETUP_NR_AREAS,
IUCV_DBF_SETUP_LEN);
iucv_dbf_data = debug_register(IUCV_DBF_DATA_NAME,
- IUCV_DBF_DATA_INDEX,
+ IUCV_DBF_DATA_PAGES,
IUCV_DBF_DATA_NR_AREAS,
IUCV_DBF_DATA_LEN);
iucv_dbf_trace = debug_register(IUCV_DBF_TRACE_NAME,
- IUCV_DBF_TRACE_INDEX,
+ IUCV_DBF_TRACE_PAGES,
IUCV_DBF_TRACE_NR_AREAS,
IUCV_DBF_TRACE_LEN);
@@ -2076,7 +2076,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write);
static void
netiucv_banner(void)
{
- char vbuf[] = "$Revision: 1.63 $";
+ char vbuf[] = "$Revision: 1.66 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index a755b57db46..3a0285669ad 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -42,44 +42,44 @@
*/
#define QETH_DBF_SETUP_NAME "qeth_setup"
#define QETH_DBF_SETUP_LEN 8
-#define QETH_DBF_SETUP_INDEX 3
+#define QETH_DBF_SETUP_PAGES 8
#define QETH_DBF_SETUP_NR_AREAS 1
#define QETH_DBF_SETUP_LEVEL 5
#define QETH_DBF_MISC_NAME "qeth_misc"
#define QETH_DBF_MISC_LEN 128
-#define QETH_DBF_MISC_INDEX 1
+#define QETH_DBF_MISC_PAGES 2
#define QETH_DBF_MISC_NR_AREAS 1
#define QETH_DBF_MISC_LEVEL 2
#define QETH_DBF_DATA_NAME "qeth_data"
#define QETH_DBF_DATA_LEN 96
-#define QETH_DBF_DATA_INDEX 3
+#define QETH_DBF_DATA_PAGES 8
#define QETH_DBF_DATA_NR_AREAS 1
#define QETH_DBF_DATA_LEVEL 2
#define QETH_DBF_CONTROL_NAME "qeth_control"
#define QETH_DBF_CONTROL_LEN 256
-#define QETH_DBF_CONTROL_INDEX 3
+#define QETH_DBF_CONTROL_PAGES 8
#define QETH_DBF_CONTROL_NR_AREAS 2
#define QETH_DBF_CONTROL_LEVEL 5
#define QETH_DBF_TRACE_NAME "qeth_trace"
#define QETH_DBF_TRACE_LEN 8
-#define QETH_DBF_TRACE_INDEX 2
+#define QETH_DBF_TRACE_PAGES 4
#define QETH_DBF_TRACE_NR_AREAS 2
#define QETH_DBF_TRACE_LEVEL 3
extern debug_info_t *qeth_dbf_trace;
#define QETH_DBF_SENSE_NAME "qeth_sense"
#define QETH_DBF_SENSE_LEN 64
-#define QETH_DBF_SENSE_INDEX 1
+#define QETH_DBF_SENSE_PAGES 2
#define QETH_DBF_SENSE_NR_AREAS 1
#define QETH_DBF_SENSE_LEVEL 2
#define QETH_DBF_QERR_NAME "qeth_qerr"
#define QETH_DBF_QERR_LEN 8
-#define QETH_DBF_QERR_INDEX 1
+#define QETH_DBF_QERR_PAGES 2
#define QETH_DBF_QERR_NR_AREAS 2
#define QETH_DBF_QERR_LEVEL 2
@@ -824,7 +824,7 @@ extern struct list_head qeth_notify_list;
#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
-inline static __u8
+static inline __u8
qeth_get_ipa_adp_type(enum qeth_link_types link_type)
{
switch (link_type) {
@@ -835,7 +835,7 @@ qeth_get_ipa_adp_type(enum qeth_link_types link_type)
}
}
-inline static int
+static inline int
qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size)
{
struct sk_buff *new_skb = NULL;
@@ -852,6 +852,7 @@ qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size)
}
return 0;
}
+
static inline struct sk_buff *
qeth_pskb_unshare(struct sk_buff *skb, int pri)
{
@@ -863,8 +864,7 @@ qeth_pskb_unshare(struct sk_buff *skb, int pri)
return nskb;
}
-
-inline static void *
+static inline void *
qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
{
void *hdr;
@@ -887,7 +887,7 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
}
-inline static int
+static inline int
qeth_get_hlen(__u8 link_type)
{
#ifdef CONFIG_QETH_IPV6
@@ -911,7 +911,7 @@ qeth_get_hlen(__u8 link_type)
#endif /* CONFIG_QETH_IPV6 */
}
-inline static unsigned short
+static inline unsigned short
qeth_get_netdev_flags(struct qeth_card *card)
{
if (card->options.layer2)
@@ -929,7 +929,7 @@ qeth_get_netdev_flags(struct qeth_card *card)
}
}
-inline static int
+static inline int
qeth_get_initial_mtu_for_card(struct qeth_card * card)
{
switch (card->info.type) {
@@ -950,7 +950,7 @@ qeth_get_initial_mtu_for_card(struct qeth_card * card)
}
}
-inline static int
+static inline int
qeth_get_max_mtu_for_card(int cardtype)
{
switch (cardtype) {
@@ -965,7 +965,7 @@ qeth_get_max_mtu_for_card(int cardtype)
}
}
-inline static int
+static inline int
qeth_get_mtu_out_of_mpc(int cardtype)
{
switch (cardtype) {
@@ -976,7 +976,7 @@ qeth_get_mtu_out_of_mpc(int cardtype)
}
}
-inline static int
+static inline int
qeth_get_mtu_outof_framesize(int framesize)
{
switch (framesize) {
@@ -993,7 +993,7 @@ qeth_get_mtu_outof_framesize(int framesize)
}
}
-inline static int
+static inline int
qeth_mtu_is_valid(struct qeth_card * card, int mtu)
{
switch (card->info.type) {
@@ -1008,7 +1008,7 @@ qeth_mtu_is_valid(struct qeth_card * card, int mtu)
}
}
-inline static int
+static inline int
qeth_get_arphdr_type(int cardtype, int linktype)
{
switch (cardtype) {
@@ -1027,7 +1027,7 @@ qeth_get_arphdr_type(int cardtype, int linktype)
}
#ifdef CONFIG_QETH_PERF_STATS
-inline static int
+static inline int
qeth_get_micros(void)
{
return (int) (get_clock() >> 12);
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 208127a5033..79c74f3a11f 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -2210,7 +2210,7 @@ no_mem:
return NULL;
}
-static inline unsigned short
+static inline __be16
qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
struct qeth_card *card;
@@ -7639,31 +7639,31 @@ static int
qeth_register_dbf_views(void)
{
qeth_dbf_setup = debug_register(QETH_DBF_SETUP_NAME,
- QETH_DBF_SETUP_INDEX,
+ QETH_DBF_SETUP_PAGES,
QETH_DBF_SETUP_NR_AREAS,
QETH_DBF_SETUP_LEN);
qeth_dbf_misc = debug_register(QETH_DBF_MISC_NAME,
- QETH_DBF_MISC_INDEX,
+ QETH_DBF_MISC_PAGES,
QETH_DBF_MISC_NR_AREAS,
QETH_DBF_MISC_LEN);
qeth_dbf_data = debug_register(QETH_DBF_DATA_NAME,
- QETH_DBF_DATA_INDEX,
+ QETH_DBF_DATA_PAGES,
QETH_DBF_DATA_NR_AREAS,
QETH_DBF_DATA_LEN);
qeth_dbf_control = debug_register(QETH_DBF_CONTROL_NAME,
- QETH_DBF_CONTROL_INDEX,
+ QETH_DBF_CONTROL_PAGES,
QETH_DBF_CONTROL_NR_AREAS,
QETH_DBF_CONTROL_LEN);
qeth_dbf_sense = debug_register(QETH_DBF_SENSE_NAME,
- QETH_DBF_SENSE_INDEX,
+ QETH_DBF_SENSE_PAGES,
QETH_DBF_SENSE_NR_AREAS,
QETH_DBF_SENSE_LEN);
qeth_dbf_qerr = debug_register(QETH_DBF_QERR_NAME,
- QETH_DBF_QERR_INDEX,
+ QETH_DBF_QERR_PAGES,
QETH_DBF_QERR_NR_AREAS,
QETH_DBF_QERR_LEN);
qeth_dbf_trace = debug_register(QETH_DBF_TRACE_NAME,
- QETH_DBF_TRACE_INDEX,
+ QETH_DBF_TRACE_PAGES,
QETH_DBF_TRACE_NR_AREAS,
QETH_DBF_TRACE_LEN);
@@ -8120,20 +8120,22 @@ static struct notifier_block qeth_ip6_notifier = {
#endif
static int
-qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+__qeth_reboot_event_card(struct device *dev, void *data)
{
-
- struct device *entry;
struct qeth_card *card;
- down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
- list_for_each_entry(entry, &qeth_ccwgroup_driver.driver.devices,
- driver_list) {
- card = (struct qeth_card *) entry->driver_data;
- qeth_clear_ip_list(card, 0, 0);
- qeth_qdio_clear_card(card, 0);
- }
- up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
+ card = (struct qeth_card *) dev->driver_data;
+ qeth_clear_ip_list(card, 0, 0);
+ qeth_qdio_clear_card(card, 0);
+ return 0;
+}
+
+static int
+qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+
+ driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+ __qeth_reboot_event_card);
return NOTIFY_DONE;
}
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 04719196fd2..f2ccfea8fdb 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -27,23 +27,33 @@ const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $";
#define QETH_PROCFILE_NAME "qeth"
static struct proc_dir_entry *qeth_procfile;
+static int
+qeth_procfile_seq_match(struct device *dev, void *data)
+{
+ return 1;
+}
+
static void *
qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
{
- struct list_head *next_card = NULL;
- int i = 0;
+ struct device *dev;
+ loff_t nr;
down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
- if (*offset == 0)
+ nr = *offset;
+ if (nr == 0)
return SEQ_START_TOKEN;
- /* get card at pos *offset */
- list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices)
- if (++i == *offset)
- return next_card;
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL,
+ NULL, qeth_procfile_seq_match);
- return NULL;
+ /* get card at pos *offset */
+ nr = *offset;
+ while (nr-- > 1 && dev)
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+ NULL, qeth_procfile_seq_match);
+ return (void *) dev;
}
static void
@@ -55,23 +65,21 @@ qeth_procfile_seq_stop(struct seq_file *s, void* it)
static void *
qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
{
- struct list_head *next_card = NULL;
- struct list_head *current_card;
+ struct device *prev, *next;
if (it == SEQ_START_TOKEN) {
- next_card = qeth_ccwgroup_driver.driver.devices.next;
- if (next_card->next == next_card) /* list empty */
- return NULL;
- (*offset)++;
- } else {
- current_card = (struct list_head *)it;
- if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
- return NULL; /* end of list reached */
- next_card = current_card->next;
- (*offset)++;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver,
+ NULL, NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
-
- return next_card;
+ prev = (struct device *) it;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver,
+ prev, NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
static inline const char *
@@ -126,7 +134,7 @@ qeth_procfile_seq_show(struct seq_file *s, void *it)
"-------------- ---- ------ ---------- ---- "
"---- ----- -----\n");
} else {
- device = list_entry(it, struct device, driver_list);
+ device = (struct device *) it;
card = device->driver_data;
seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ",
CARD_RDEV_ID(card),
@@ -180,17 +188,20 @@ static struct proc_dir_entry *qeth_perf_procfile;
static void *
qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset)
{
- struct list_head *next_card = NULL;
- int i = 0;
+ struct device *dev = NULL;
+ int nr;
down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
/* get card at pos *offset */
- list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
- if (i == *offset)
- return next_card;
- i++;
- }
- return NULL;
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+ qeth_procfile_seq_match);
+
+ /* get card at pos *offset */
+ nr = *offset;
+ while (nr-- > 1 && dev)
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+ NULL, qeth_procfile_seq_match);
+ return (void *) dev;
}
static void
@@ -202,12 +213,14 @@ qeth_perf_procfile_seq_stop(struct seq_file *s, void* it)
static void *
qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
{
- struct list_head *current_card = (struct list_head *)it;
+ struct device *prev, *next;
- if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
- return NULL; /* end of list reached */
- (*offset)++;
- return current_card->next;
+ prev = (struct device *) it;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver, prev,
+ NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
static int
@@ -216,7 +229,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
struct device *device;
struct qeth_card *card;
- device = list_entry(it, struct device, driver_list);
+ device = (struct device *) it;
card = device->driver_data;
seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
CARD_RDEV_ID(card),
@@ -318,8 +331,8 @@ static struct proc_dir_entry *qeth_ipato_procfile;
static void *
qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
{
- struct list_head *next_card = NULL;
- int i = 0;
+ struct device *dev;
+ loff_t nr;
down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
/* TODO: finish this */
@@ -328,13 +341,16 @@ qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset)
* output driver settings then;
* else output setting for respective card
*/
+
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+ qeth_procfile_seq_match);
+
/* get card at pos *offset */
- list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){
- if (i == *offset)
- return next_card;
- i++;
- }
- return NULL;
+ nr = *offset;
+ while (nr-- > 1 && dev)
+ dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+ NULL, qeth_procfile_seq_match);
+ return (void *) dev;
}
static void
@@ -346,18 +362,14 @@ qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it)
static void *
qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
{
- struct list_head *current_card = (struct list_head *)it;
+ struct device *prev, *next;
- /* TODO: finish this */
- /*
- * maybe SEQ_SATRT_TOKEN can be returned for offset 0
- * output driver settings then;
- * else output setting for respective card
- */
- if (current_card->next == &qeth_ccwgroup_driver.driver.devices)
- return NULL; /* end of list reached */
- (*offset)++;
- return current_card->next;
+ prev = (struct device *) it;
+ next = driver_find_device(&qeth_ccwgroup_driver.driver, prev,
+ NULL, qeth_procfile_seq_match);
+ if (next)
+ (*offset)++;
+ return (void *) next;
}
static int
@@ -372,7 +384,7 @@ qeth_ipato_procfile_seq_show(struct seq_file *s, void *it)
* output driver settings then;
* else output setting for respective card
*/
- device = list_entry(it, struct device, driver_list);
+ device = (struct device *) it;
card = device->driver_data;
return 0;
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index 1e3f7f3c662..d6469baa7e1 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -138,7 +138,7 @@ static void __exit
smsg_exit(void)
{
if (smsg_handle > 0) {
- cpcmd("SET SMSG OFF", 0, 0);
+ cpcmd("SET SMSG OFF", NULL, 0, NULL);
iucv_sever(smsg_pathid, 0);
iucv_unregister_program(smsg_handle);
driver_unregister(&smsg_driver);
@@ -177,7 +177,7 @@ smsg_init(void)
smsg_handle = 0;
return -EIO;
}
- cpcmd("SET SMSG IUCV", 0, 0);
+ cpcmd("SET SMSG IUCV", NULL, 0, NULL);
return 0;
}
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index ffa996c8a90..5bb255e02ac 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -31,14 +31,14 @@ extern void css_reiterate_subchannels(void);
extern struct workqueue_struct *slow_path_wq;
extern struct work_struct slow_path_work;
-static void
+static NORET_TYPE void
s390_handle_damage(char *msg)
{
- printk(KERN_EMERG "%s\n", msg);
#ifdef CONFIG_SMP
smp_send_stop();
#endif
disabled_wait((unsigned long) __builtin_return_address(0));
+ for(;;);
}
/*
@@ -122,40 +122,39 @@ repeat:
return 0;
}
+struct mcck_struct {
+ int kill_task;
+ int channel_report;
+ int warning;
+ unsigned long long mcck_code;
+};
+
+static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck);
+
/*
- * machine check handler.
+ * Main machine check handler function. Will be called with interrupts enabled
+ * or disabled and machine checks enabled or disabled.
*/
void
-s390_do_machine_check(void)
+s390_handle_mcck(void)
{
- struct mci *mci;
-
- mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
+ unsigned long flags;
+ struct mcck_struct mcck;
- if (mci->sd) /* system damage */
- s390_handle_damage("received system damage machine check\n");
+ /*
+ * Disable machine checks and get the current state of accumulated
+ * machine checks. Afterwards delete the old state and enable machine
+ * checks again.
+ */
+ local_irq_save(flags);
+ local_mcck_disable();
+ mcck = __get_cpu_var(cpu_mcck);
+ memset(&__get_cpu_var(cpu_mcck), 0, sizeof(struct mcck_struct));
+ clear_thread_flag(TIF_MCCK_PENDING);
+ local_mcck_enable();
+ local_irq_restore(flags);
- if (mci->pd) /* instruction processing damage */
- s390_handle_damage("received instruction processing "
- "damage machine check\n");
-
- if (mci->se) /* storage error uncorrected */
- s390_handle_damage("received storage error uncorrected "
- "machine check\n");
-
- if (mci->sc) /* storage error corrected */
- printk(KERN_WARNING
- "received storage error corrected machine check\n");
-
- if (mci->ke) /* storage key-error uncorrected */
- s390_handle_damage("received storage key-error uncorrected "
- "machine check\n");
-
- if (mci->ds && mci->fa) /* storage degradation */
- s390_handle_damage("received storage degradation machine "
- "check\n");
-
- if (mci->cp) /* channel report word pending */
+ if (mcck.channel_report)
up(&m_sem);
#ifdef CONFIG_MACHCHK_WARNING
@@ -168,7 +167,7 @@ s390_do_machine_check(void)
* On VM we only get one interrupt per virtally presented machinecheck.
* Though one suffices, we may get one interrupt per (virtual) processor.
*/
- if (mci->w) { /* WARNING pending ? */
+ if (mcck.warning) { /* WARNING pending ? */
static int mchchk_wng_posted = 0;
/*
* Use single machine clear, as we cannot handle smp right now
@@ -178,6 +177,261 @@ s390_do_machine_check(void)
kill_proc(1, SIGPWR, 1);
}
#endif
+
+ if (mcck.kill_task) {
+ local_irq_enable();
+ printk(KERN_EMERG "mcck: Terminating task because of machine "
+ "malfunction (code 0x%016llx).\n", mcck.mcck_code);
+ printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
+ current->comm, current->pid);
+ do_exit(SIGSEGV);
+ }
+}
+
+/*
+ * returns 0 if all registers could be validated
+ * returns 1 otherwise
+ */
+static int
+s390_revalidate_registers(struct mci *mci)
+{
+ int kill_task;
+ u64 tmpclock;
+ u64 zero;
+ void *fpt_save_area, *fpt_creg_save_area;
+
+ kill_task = 0;
+ zero = 0;
+ /* General purpose registers */
+ if (!mci->gr)
+ /*
+ * General purpose registers couldn't be restored and have
+ * unknown contents. Process needs to be terminated.
+ */
+ kill_task = 1;
+
+ /* Revalidate floating point registers */
+ if (!mci->fp)
+ /*
+ * Floating point registers can't be restored and
+ * therefore the process needs to be terminated.
+ */
+ kill_task = 1;
+
+#ifndef __s390x__
+ asm volatile("ld 0,0(%0)\n"
+ "ld 2,8(%0)\n"
+ "ld 4,16(%0)\n"
+ "ld 6,24(%0)"
+ : : "a" (&S390_lowcore.floating_pt_save_area));
+#endif
+
+ if (MACHINE_HAS_IEEE) {
+#ifdef __s390x__
+ fpt_save_area = &S390_lowcore.floating_pt_save_area;
+ fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
+#else
+ fpt_save_area = (void *) S390_lowcore.extended_save_area_addr;
+ fpt_creg_save_area = fpt_save_area+128;
+#endif
+ /* Floating point control register */
+ if (!mci->fc) {
+ /*
+ * Floating point control register can't be restored.
+ * Task will be terminated.
+ */
+ asm volatile ("lfpc 0(%0)" : : "a" (&zero));
+ kill_task = 1;
+
+ }
+ else
+ asm volatile (
+ "lfpc 0(%0)"
+ : : "a" (fpt_creg_save_area));
+
+ asm volatile("ld 0,0(%0)\n"
+ "ld 1,8(%0)\n"
+ "ld 2,16(%0)\n"
+ "ld 3,24(%0)\n"
+ "ld 4,32(%0)\n"
+ "ld 5,40(%0)\n"
+ "ld 6,48(%0)\n"
+ "ld 7,56(%0)\n"
+ "ld 8,64(%0)\n"
+ "ld 9,72(%0)\n"
+ "ld 10,80(%0)\n"
+ "ld 11,88(%0)\n"
+ "ld 12,96(%0)\n"
+ "ld 13,104(%0)\n"
+ "ld 14,112(%0)\n"
+ "ld 15,120(%0)\n"
+ : : "a" (fpt_save_area));
+ }
+
+ /* Revalidate access registers */
+ asm volatile("lam 0,15,0(%0)"
+ : : "a" (&S390_lowcore.access_regs_save_area));
+ if (!mci->ar)
+ /*
+ * Access registers have unknown contents.
+ * Terminating task.
+ */
+ kill_task = 1;
+
+ /* Revalidate control registers */
+ if (!mci->cr)
+ /*
+ * Control registers have unknown contents.
+ * Can't recover and therefore stopping machine.
+ */
+ s390_handle_damage("invalid control registers.");
+ else
+#ifdef __s390x__
+ asm volatile("lctlg 0,15,0(%0)"
+ : : "a" (&S390_lowcore.cregs_save_area));
+#else
+ asm volatile("lctl 0,15,0(%0)"
+ : : "a" (&S390_lowcore.cregs_save_area));
+#endif
+
+ /*
+ * We don't even try to revalidate the TOD register, since we simply
+ * can't write something sensible into that register.
+ */
+
+#ifdef __s390x__
+ /*
+ * See if we can revalidate the TOD programmable register with its
+ * old contents (should be zero) otherwise set it to zero.
+ */
+ if (!mci->pr)
+ asm volatile("sr 0,0\n"
+ "sckpf"
+ : : : "0", "cc");
+ else
+ asm volatile(
+ "l 0,0(%0)\n"
+ "sckpf"
+ : : "a" (&S390_lowcore.tod_progreg_save_area) : "0", "cc");
+#endif
+
+ /* Revalidate clock comparator register */
+ asm volatile ("stck 0(%1)\n"
+ "sckc 0(%1)"
+ : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
+
+ /* Check if old PSW is valid */
+ if (!mci->wp)
+ /*
+ * Can't tell if we come from user or kernel mode
+ * -> stopping machine.
+ */
+ s390_handle_damage("old psw invalid.");
+
+ if (!mci->ms || !mci->pm || !mci->ia)
+ kill_task = 1;
+
+ return kill_task;
+}
+
+/*
+ * machine check handler.
+ */
+void
+s390_do_machine_check(struct pt_regs *regs)
+{
+ struct mci *mci;
+ struct mcck_struct *mcck;
+ int umode;
+
+ mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
+ mcck = &__get_cpu_var(cpu_mcck);
+ umode = user_mode(regs);
+
+ if (mci->sd)
+ /* System damage -> stopping machine */
+ s390_handle_damage("received system damage machine check.");
+
+ if (mci->pd) {
+ if (mci->b) {
+ /* Processing backup -> verify if we can survive this */
+ u64 z_mcic, o_mcic, t_mcic;
+#ifdef __s390x__
+ z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29);
+ o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
+ 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
+ 1ULL<<30 | 1ULL<<21 | 1ULL<<20 | 1ULL<<17 |
+ 1ULL<<16);
+#else
+ z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<57 | 1ULL<<50 |
+ 1ULL<<29);
+ o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
+ 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
+ 1ULL<<30 | 1ULL<<20 | 1ULL<<17 | 1ULL<<16);
+#endif
+ t_mcic = *(u64 *)mci;
+
+ if (((t_mcic & z_mcic) != 0) ||
+ ((t_mcic & o_mcic) != o_mcic)) {
+ s390_handle_damage("processing backup machine "
+ "check with damage.");
+ }
+ if (!umode)
+ s390_handle_damage("processing backup machine "
+ "check in kernel mode.");
+ mcck->kill_task = 1;
+ mcck->mcck_code = *(unsigned long long *) mci;
+ }
+ else {
+ /* Processing damage -> stopping machine */
+ s390_handle_damage("received instruction processing "
+ "damage machine check.");
+ }
+ }
+ if (s390_revalidate_registers(mci)) {
+ if (umode) {
+ /*
+ * Couldn't restore all register contents while in
+ * user mode -> mark task for termination.
+ */
+ mcck->kill_task = 1;
+ mcck->mcck_code = *(unsigned long long *) mci;
+ set_thread_flag(TIF_MCCK_PENDING);
+ }
+ else
+ /*
+ * Couldn't restore all register contents while in
+ * kernel mode -> stopping machine.
+ */
+ s390_handle_damage("unable to revalidate registers.");
+ }
+
+ if (mci->se)
+ /* Storage error uncorrected */
+ s390_handle_damage("received storage error uncorrected "
+ "machine check.");
+
+ if (mci->ke)
+ /* Storage key-error uncorrected */
+ s390_handle_damage("received storage key-error uncorrected "
+ "machine check.");
+
+ if (mci->ds && mci->fa)
+ /* Storage degradation */
+ s390_handle_damage("received storage degradation machine "
+ "check.");
+
+ if (mci->cp) {
+ /* Channel report word pending */
+ mcck->channel_report = 1;
+ set_thread_flag(TIF_MCCK_PENDING);
+ }
+
+ if (mci->w) {
+ /* Warning pending */
+ mcck->warning = 1;
+ set_thread_flag(TIF_MCCK_PENDING);
+ }
}
/*
@@ -189,9 +443,8 @@ static int
machine_check_init(void)
{
init_MUTEX_LOCKED(&m_sem);
- ctl_clear_bit(14, 25); /* disable damage MCH */
- ctl_set_bit(14, 26); /* enable degradation MCH */
- ctl_set_bit(14, 27); /* enable system recovery MCH */
+ ctl_clear_bit(14, 25); /* disable external damage MCH */
+ ctl_set_bit(14, 27); /* enable system recovery MCH */
#ifdef CONFIG_MACHCHK_WARNING
ctl_set_bit(14, 24); /* enable warning MCH */
#endif
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
index 7e26f0f1b0d..4eaa7017918 100644
--- a/drivers/s390/s390mach.h
+++ b/drivers/s390/s390mach.h
@@ -16,20 +16,45 @@ struct mci {
__u32 sd : 1; /* 00 system damage */
__u32 pd : 1; /* 01 instruction-processing damage */
__u32 sr : 1; /* 02 system recovery */
- __u32 to_be_defined_1 : 4; /* 03-06 */
+ __u32 to_be_defined_1 : 1; /* 03 */
+ __u32 cd : 1; /* 04 timing-facility damage */
+ __u32 ed : 1; /* 05 external damage */
+ __u32 to_be_defined_2 : 1; /* 06 */
__u32 dg : 1; /* 07 degradation */
__u32 w : 1; /* 08 warning pending */
__u32 cp : 1; /* 09 channel-report pending */
- __u32 to_be_defined_2 : 6; /* 10-15 */
+ __u32 sp : 1; /* 10 service-processor damage */
+ __u32 ck : 1; /* 11 channel-subsystem damage */
+ __u32 to_be_defined_3 : 2; /* 12-13 */
+ __u32 b : 1; /* 14 backed up */
+ __u32 to_be_defined_4 : 1; /* 15 */
__u32 se : 1; /* 16 storage error uncorrected */
__u32 sc : 1; /* 17 storage error corrected */
__u32 ke : 1; /* 18 storage-key error uncorrected */
__u32 ds : 1; /* 19 storage degradation */
- __u32 to_be_defined_3 : 4; /* 20-23 */
+ __u32 wp : 1; /* 20 psw mwp validity */
+ __u32 ms : 1; /* 21 psw mask and key validity */
+ __u32 pm : 1; /* 22 psw program mask and cc validity */
+ __u32 ia : 1; /* 23 psw instruction address validity */
__u32 fa : 1; /* 24 failing storage address validity */
- __u32 to_be_defined_4 : 7; /* 25-31 */
+ __u32 to_be_defined_5 : 1; /* 25 */
+ __u32 ec : 1; /* 26 external damage code validity */
+ __u32 fp : 1; /* 27 floating point register validity */
+ __u32 gr : 1; /* 28 general register validity */
+ __u32 cr : 1; /* 29 control register validity */
+ __u32 to_be_defined_6 : 1; /* 30 */
+ __u32 st : 1; /* 31 storage logical validity */
__u32 ie : 1; /* 32 indirect storage error */
- __u32 to_be_defined_5 : 31; /* 33-63 */
+ __u32 ar : 1; /* 33 access register validity */
+ __u32 da : 1; /* 34 delayed access exception */
+ __u32 to_be_defined_7 : 7; /* 35-41 */
+ __u32 pr : 1; /* 42 tod programmable register validity */
+ __u32 fc : 1; /* 43 fp control register validity */
+ __u32 ap : 1; /* 44 ancillary report */
+ __u32 to_be_defined_8 : 1; /* 45 */
+ __u32 ct : 1; /* 46 cpu timer validity */
+ __u32 cc : 1; /* 47 clock comparator validity */
+ __u32 to_be_defined_9 : 16; /* 47-63 */
};
/*
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index e17b4d58a9f..bfe3ba73bc0 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -1299,13 +1299,10 @@ struct zfcp_port *
zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
u32 d_id)
{
- struct zfcp_port *port, *tmp_port;
+ struct zfcp_port *port;
int check_wwpn;
- scsi_id_t scsi_id;
- int found;
check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN);
-
/*
* check that there is no port with this WWPN already in list
*/
@@ -1368,7 +1365,7 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
} else {
snprintf(port->sysfs_device.bus_id,
BUS_ID_SIZE, "0x%016llx", wwpn);
- port->sysfs_device.parent = &adapter->ccw_device->dev;
+ port->sysfs_device.parent = &adapter->ccw_device->dev;
}
port->sysfs_device.release = zfcp_sysfs_port_release;
dev_set_drvdata(&port->sysfs_device, port);
@@ -1388,24 +1385,8 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
zfcp_port_get(port);
- scsi_id = 1;
- found = 0;
write_lock_irq(&zfcp_data.config_lock);
- list_for_each_entry(tmp_port, &adapter->port_list_head, list) {
- if (atomic_test_mask(ZFCP_STATUS_PORT_NO_SCSI_ID,
- &tmp_port->status))
- continue;
- if (tmp_port->scsi_id != scsi_id) {
- found = 1;
- break;
- }
- scsi_id++;
- }
- port->scsi_id = scsi_id;
- if (found)
- list_add_tail(&port->list, &tmp_port->list);
- else
- list_add_tail(&port->list, &adapter->port_list_head);
+ list_add_tail(&port->list, &adapter->port_list_head);
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
if (d_id == ZFCP_DID_DIRECTORY_SERVICE)
@@ -1427,6 +1408,9 @@ zfcp_port_dequeue(struct zfcp_port *port)
list_del(&port->list);
port->adapter->ports--;
write_unlock_irq(&zfcp_data.config_lock);
+ if (port->rport)
+ fc_remote_port_delete(port->rport);
+ port->rport = NULL;
zfcp_adapter_put(port->adapter);
zfcp_sysfs_port_remove_files(&port->sysfs_device,
atomic_read(&port->status));
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 0fc46381fc2..b30abab77da 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -202,9 +202,19 @@ static int
zfcp_ccw_set_offline(struct ccw_device *ccw_device)
{
struct zfcp_adapter *adapter;
+ struct zfcp_port *port;
+ struct fc_rport *rport;
down(&zfcp_data.config_sema);
adapter = dev_get_drvdata(&ccw_device->dev);
+ /* might be racy, but we cannot take config_lock due to the fact that
+ fc_remote_port_delete might sleep */
+ list_for_each_entry(port, &adapter->port_list_head, list)
+ if (port->rport) {
+ rport = port->rport;
+ port->rport = NULL;
+ fc_remote_port_delete(rport);
+ }
zfcp_erp_adapter_shutdown(adapter, 0);
zfcp_erp_wait(adapter);
zfcp_adapter_scsi_unregister(adapter);
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 4103b5be768..455e902533a 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -906,6 +906,7 @@ struct zfcp_adapter {
*/
struct zfcp_port {
struct device sysfs_device; /* sysfs device */
+ struct fc_rport *rport; /* rport of fc transport class */
struct list_head list; /* list of remote ports */
atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for
@@ -916,7 +917,6 @@ struct zfcp_port {
list */
u32 units; /* # of logical units in list */
atomic_t status; /* status of this remote port */
- scsi_id_t scsi_id; /* own SCSI ID */
wwn_t wwnn; /* WWNN if known */
wwn_t wwpn; /* WWPN */
fc_id_t d_id; /* D_ID */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 0cf31f7d1c0..cb4f612550b 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -3360,13 +3360,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
if ((result == ZFCP_ERP_SUCCEEDED)
&& (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY,
&unit->status))
- && (!unit->device))
- scsi_add_device(unit->port->adapter->scsi_host, 0,
- unit->port->scsi_id, unit->scsi_lun);
+ && !unit->device
+ && port->rport)
+ scsi_add_device(port->adapter->scsi_host, 0,
+ port->rport->scsi_target_id,
+ unit->scsi_lun);
zfcp_unit_put(unit);
break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
case ZFCP_ERP_ACTION_REOPEN_PORT:
+ if ((result == ZFCP_ERP_SUCCEEDED)
+ && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
+ &port->status)
+ && !port->rport) {
+ struct fc_rport_identifiers ids;
+ ids.node_name = port->wwnn;
+ ids.port_name = port->wwpn;
+ ids.port_id = port->d_id;
+ ids.roles = FC_RPORT_ROLE_FCP_TARGET;
+ port->rport =
+ fc_remote_port_add(adapter->scsi_host, 0, &ids);
+ if (!port->rport)
+ ZFCP_LOG_NORMAL("failed registration of rport"
+ "(adapter %s, wwpn=0x%016Lx)\n",
+ zfcp_get_busid_by_port(port),
+ port->wwpn);
+ }
zfcp_port_put(port);
break;
case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 42df7e57eea..cd98a2de9f8 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -143,6 +143,8 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
struct scsi_cmnd *, struct timer_list *);
extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
struct timer_list *);
+extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *);
+extern void zfcp_set_fc_rport_attrs(struct zfcp_port *);
extern struct scsi_transport_template *zfcp_transport_template;
extern struct fc_function_template zfcp_transport_functions;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 0d9f20edc49..c007b6424e7 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -2062,6 +2062,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
zfcp_erp_adapter_shutdown(adapter, 0);
return -EIO;
}
+ zfcp_set_fc_host_attrs(adapter);
return 0;
}
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index b61d309352c..31a76065cf2 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -389,7 +389,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
struct zfcp_unit *unit, *retval = NULL;
list_for_each_entry(port, &adapter->port_list_head, list) {
- if (id != port->scsi_id)
+ if (!port->rport || (id != port->rport->scsi_target_id))
continue;
list_for_each_entry(unit, &port->unit_list_head, list) {
if (lun == unit->scsi_lun) {
@@ -408,7 +408,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
struct zfcp_port *port;
list_for_each_entry(port, &adapter->port_list_head, list) {
- if (id == port->scsi_id)
+ if (port->rport && (id == port->rport->scsi_target_id))
return port;
}
return (struct zfcp_port *) NULL;
@@ -634,7 +634,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
{
int retval;
struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
- struct Scsi_Host *scsi_host = scpnt->device->host;
if (!unit) {
ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
@@ -729,7 +728,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
{
int retval = 0;
struct zfcp_unit *unit;
- struct Scsi_Host *scsi_host = scpnt->device->host;
unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("bus reset because of problems with "
@@ -753,7 +751,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{
int retval = 0;
struct zfcp_unit *unit;
- struct Scsi_Host *scsi_host = scpnt->device->host;
unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("host reset because of problems with "
@@ -833,6 +830,7 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
shost = adapter->scsi_host;
if (!shost)
return;
+ fc_remove_host(shost);
scsi_remove_host(shost);
scsi_host_put(shost);
adapter->scsi_host = NULL;
@@ -906,6 +904,18 @@ zfcp_get_node_name(struct scsi_target *starget)
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
+void
+zfcp_set_fc_host_attrs(struct zfcp_adapter *adapter)
+{
+ struct Scsi_Host *shost = adapter->scsi_host;
+
+ fc_host_node_name(shost) = adapter->wwnn;
+ fc_host_port_name(shost) = adapter->wwpn;
+ strncpy(fc_host_serial_number(shost), adapter->serial_number,
+ min(FC_SERIAL_NUMBER_SIZE, 32));
+ fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
+}
+
struct fc_function_template zfcp_transport_functions = {
.get_starget_port_id = zfcp_get_port_id,
.get_starget_port_name = zfcp_get_port_name,
@@ -913,6 +923,11 @@ struct fc_function_template zfcp_transport_functions = {
.show_starget_port_id = 1,
.show_starget_port_name = 1,
.show_starget_node_name = 1,
+ .show_rport_supported_classes = 1,
+ .show_host_node_name = 1,
+ .show_host_port_name = 1,
+ .show_host_supported_classes = 1,
+ .show_host_serial_number = 1,
};
/**
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index 7a84c7d474d..c55e82d91de 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -67,7 +67,6 @@ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL);
ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status));
ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
-ZFCP_DEFINE_PORT_ATTR(scsi_id, "0x%x\n", port->scsi_id);
ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -263,7 +262,6 @@ static struct attribute_group zfcp_port_common_attr_group = {
static struct attribute *zfcp_port_no_ns_attrs[] = {
&dev_attr_unit_add.attr,
&dev_attr_unit_remove.attr,
- &dev_attr_scsi_id.attr,
NULL
};