aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/Kconfig14
-rw-r--r--drivers/s390/block/Makefile2
-rw-r--r--drivers/s390/block/dasd.c97
-rw-r--r--drivers/s390/block/dasd_3990_erp.c3
-rw-r--r--drivers/s390/block/dasd_eckd.h1
-rw-r--r--drivers/s390/block/dasd_eer.c1090
-rw-r--r--drivers/s390/block/dasd_int.h38
-rw-r--r--drivers/s390/char/sclp.c13
-rw-r--r--drivers/s390/cio/chsc.c10
-rw-r--r--drivers/s390/cio/device.c2
-rw-r--r--drivers/s390/cio/device_pgid.c2
-rw-r--r--drivers/s390/cio/device_status.c1
-rw-r--r--drivers/s390/cio/qdio.c13
-rw-r--r--drivers/s390/net/lcs.c31
-rw-r--r--drivers/s390/net/lcs.h2
-rw-r--r--drivers/s390/net/qeth.h112
-rw-r--r--drivers/s390/net/qeth_eddp.c11
-rw-r--r--drivers/s390/net/qeth_main.c17
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c76
-rw-r--r--drivers/s390/scsi/zfcp_def.h13
-rw-r--r--drivers/s390/scsi/zfcp_erp.c82
-rw-r--r--drivers/s390/scsi/zfcp_ext.h5
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c80
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c15
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_adapter.c4
25 files changed, 247 insertions, 1487 deletions
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 6912399d093709..6f50cc9323d959 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -55,21 +55,13 @@ config DASD_DIAG
Disks under VM. If you are not running under VM or unsure what it is,
say "N".
-config DASD_EER
- tristate "Extended error reporting (EER)"
- depends on DASD
- help
- This driver provides a character device interface to the
- DASD extended error reporting. This is only needed if you want to
- use applications written for the EER facility.
-
config DASD_CMB
tristate "Compatibility interface for DASD channel measurement blocks"
depends on DASD
help
- This driver provides an additional interface to the channel
- measurement facility, which is normally accessed though sysfs, with
- a set of ioctl functions specific to the dasd driver.
+ This driver provides an additional interface to the channel measurement
+ facility, which is normally accessed though sysfs, with a set of
+ ioctl functions specific to the dasd driver.
This is only needed if you want to use applications written for
linux-2.4 dasd channel measurement facility interface.
diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile
index 0c0d871e8f512f..58c6780134f748 100644
--- a/drivers/s390/block/Makefile
+++ b/drivers/s390/block/Makefile
@@ -5,7 +5,6 @@
dasd_eckd_mod-objs := dasd_eckd.o dasd_3990_erp.o dasd_9343_erp.o
dasd_fba_mod-objs := dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o
dasd_diag_mod-objs := dasd_diag.o
-dasd_eer_mod-objs := dasd_eer.o
dasd_mod-objs := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \
dasd_genhd.o dasd_erp.o
@@ -14,6 +13,5 @@ obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o
obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o
obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o
obj-$(CONFIG_DASD_CMB) += dasd_cmb.o
-obj-$(CONFIG_DASD_EER) += dasd_eer.o
obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o
obj-$(CONFIG_DCSSBLK) += dcssblk.o
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 08c88fcd896339..af1d5b404cee3f 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -18,7 +18,6 @@
#include <linux/slab.h>
#include <linux/buffer_head.h>
#include <linux/hdreg.h>
-#include <linux/notifier.h>
#include <asm/ccwdev.h>
#include <asm/ebcdic.h>
@@ -58,7 +57,6 @@ static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
static void dasd_flush_ccw_queue(struct dasd_device *, int);
static void dasd_tasklet(struct dasd_device *);
static void do_kick_device(void *data);
-static void dasd_disable_eer(struct dasd_device *device);
/*
* SECTION: Operations on the device structure.
@@ -153,10 +151,13 @@ dasd_state_new_to_known(struct dasd_device *device)
static inline void
dasd_state_known_to_new(struct dasd_device * device)
{
- /* disable extended error reporting for this device */
- dasd_disable_eer(device);
/* Forget the discipline information. */
+ if (device->discipline)
+ module_put(device->discipline->owner);
device->discipline = NULL;
+ if (device->base_discipline)
+ module_put(device->base_discipline->owner);
+ device->base_discipline = NULL;
device->state = DASD_STATE_NEW;
dasd_free_queue(device);
@@ -871,9 +872,6 @@ dasd_handle_state_change_pending(struct dasd_device *device)
struct dasd_ccw_req *cqr;
struct list_head *l, *n;
- /* first of all call extended error reporting */
- dasd_write_eer_trigger(DASD_EER_STATECHANGE, device, NULL);
-
device->stopped &= ~DASD_STOPPED_PENDING;
/* restart all 'running' IO on queue */
@@ -1093,19 +1091,6 @@ restart:
}
goto restart;
}
-
- /* first of all call extended error reporting */
- if (device->eer && cqr->status == DASD_CQR_FAILED) {
- dasd_write_eer_trigger(DASD_EER_FATALERROR,
- device, cqr);
-
- /* restart request */
- cqr->status = DASD_CQR_QUEUED;
- cqr->retries = 255;
- device->stopped |= DASD_STOPPED_QUIESCE;
- goto restart;
- }
-
/* Process finished ERP request. */
if (cqr->refers) {
__dasd_process_erp(device, cqr);
@@ -1243,8 +1228,7 @@ __dasd_start_head(struct dasd_device * device)
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
/* check FAILFAST */
if (device->stopped & ~DASD_STOPPED_PENDING &&
- test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
- (!device->eer)) {
+ test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) {
cqr->status = DASD_CQR_FAILED;
dasd_schedule_bh(device);
}
@@ -1880,9 +1864,10 @@ dasd_generic_remove (struct ccw_device *cdev)
*/
int
dasd_generic_set_online (struct ccw_device *cdev,
- struct dasd_discipline *discipline)
+ struct dasd_discipline *base_discipline)
{
+ struct dasd_discipline *discipline;
struct dasd_device *device;
int rc;
@@ -1890,6 +1875,7 @@ dasd_generic_set_online (struct ccw_device *cdev,
if (IS_ERR(device))
return PTR_ERR(device);
+ discipline = base_discipline;
if (device->features & DASD_FEATURE_USEDIAG) {
if (!dasd_diag_discipline_pointer) {
printk (KERN_WARNING
@@ -1901,6 +1887,16 @@ dasd_generic_set_online (struct ccw_device *cdev,
}
discipline = dasd_diag_discipline_pointer;
}
+ if (!try_module_get(base_discipline->owner)) {
+ dasd_delete_device(device);
+ return -EINVAL;
+ }
+ if (!try_module_get(discipline->owner)) {
+ module_put(base_discipline->owner);
+ dasd_delete_device(device);
+ return -EINVAL;
+ }
+ device->base_discipline = base_discipline;
device->discipline = discipline;
rc = discipline->check_device(device);
@@ -1909,6 +1905,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
"dasd_generic couldn't online device %s "
"with discipline %s rc=%i\n",
cdev->dev.bus_id, discipline->name, rc);
+ module_put(discipline->owner);
+ module_put(base_discipline->owner);
dasd_delete_device(device);
return rc;
}
@@ -1986,9 +1984,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
switch (event) {
case CIO_GONE:
case CIO_NO_PATH:
- /* first of all call extended error reporting */
- dasd_write_eer_trigger(DASD_EER_NOPATH, device, NULL);
-
if (device->state < DASD_STATE_BASIC)
break;
/* Device is active. We want to keep it. */
@@ -2046,51 +2041,6 @@ dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver)
put_driver(drv);
}
-/*
- * notifications for extended error reports
- */
-static struct notifier_block *dasd_eer_chain;
-
-int
-dasd_register_eer_notifier(struct notifier_block *nb)
-{
- return notifier_chain_register(&dasd_eer_chain, nb);
-}
-
-int
-dasd_unregister_eer_notifier(struct notifier_block *nb)
-{
- return notifier_chain_unregister(&dasd_eer_chain, nb);
-}
-
-/*
- * Notify the registered error reporting module of a problem
- */
-void
-dasd_write_eer_trigger(unsigned int id, struct dasd_device *device,
- struct dasd_ccw_req *cqr)
-{
- if (device->eer) {
- struct dasd_eer_trigger temp;
- temp.id = id;
- temp.device = device;
- temp.cqr = cqr;
- notifier_call_chain(&dasd_eer_chain, DASD_EER_TRIGGER,
- (void *)&temp);
- }
-}
-
-/*
- * Tell the registered error reporting module to disable error reporting for
- * a given device and to cleanup any private data structures on that device.
- */
-static void
-dasd_disable_eer(struct dasd_device *device)
-{
- notifier_call_chain(&dasd_eer_chain, DASD_EER_DISABLE, (void *)device);
-}
-
-
static int __init
dasd_init(void)
{
@@ -2172,11 +2122,6 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online);
EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
EXPORT_SYMBOL_GPL(dasd_generic_auto_online);
-EXPORT_SYMBOL(dasd_register_eer_notifier);
-EXPORT_SYMBOL(dasd_unregister_eer_notifier);
-EXPORT_SYMBOL(dasd_write_eer_trigger);
-
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index c811380b907967..4ee0f934e32538 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -1108,9 +1108,6 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
case 0x0B:
DEV_MESSAGE(KERN_WARNING, device, "%s",
"FORMAT F - Volume is suspended duplex");
- /* call extended error reporting (EER) */
- dasd_write_eer_trigger(DASD_EER_PPRCSUSPEND, device,
- erp->refers);
break;
case 0x0C:
DEV_MESSAGE(KERN_WARNING, device, "%s",
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index e15dd79780509d..bc3823d3522336 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -29,7 +29,6 @@
#define DASD_ECKD_CCW_PSF 0x27
#define DASD_ECKD_CCW_RSSD 0x3e
#define DASD_ECKD_CCW_LOCATE_RECORD 0x47
-#define DASD_ECKD_CCW_SNSS 0x54
#define DASD_ECKD_CCW_DEFINE_EXTENT 0x63
#define DASD_ECKD_CCW_WRITE_MT 0x85
#define DASD_ECKD_CCW_READ_MT 0x86
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
deleted file mode 100644
index f70cd7716b2446..00000000000000
--- a/drivers/s390/block/dasd_eer.c
+++ /dev/null
@@ -1,1090 +0,0 @@
-/*
- * character device driver for extended error reporting
- *
- *
- * Copyright (C) 2005 IBM Corporation
- * extended error reporting for DASD ECKD devices
- * Author(s): Stefan Weinhuber <wein@de.ibm.com>
- *
- */
-
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/workqueue.h>
-#include <linux/poll.h>
-#include <linux/notifier.h>
-
-#include <asm/uaccess.h>
-#include <asm/semaphore.h>
-#include <asm/atomic.h>
-#include <asm/ebcdic.h>
-
-#include "dasd_int.h"
-#include "dasd_eckd.h"
-
-
-MODULE_LICENSE("GPL");
-
-MODULE_AUTHOR("Stefan Weinhuber <wein@de.ibm.com>");
-MODULE_DESCRIPTION("DASD extended error reporting module");
-
-
-#ifdef PRINTK_HEADER
-#undef PRINTK_HEADER
-#endif /* PRINTK_HEADER */
-#define PRINTK_HEADER "dasd(eer):"
-
-
-
-
-
-/*****************************************************************************/
-/* the internal buffer */
-/*****************************************************************************/
-
-/*
- * The internal buffer is meant to store obaque blobs of data, so it doesn't
- * know of higher level concepts like triggers.
- * It consists of a number of pages that are used as a ringbuffer. Each data
- * blob is stored in a simple record that consists of an integer, which
- * contains the size of the following data, and the data bytes themselfes.
- *
- * To allow for multiple independent readers we create one internal buffer
- * each time the device is opened and destroy the buffer when the file is
- * closed again.
- *
- * One record can be written to a buffer by using the functions
- * - dasd_eer_start_record (one time per record to write the size to the buffer
- * and reserve the space for the data)
- * - dasd_eer_write_buffer (one or more times per record to write the data)
- * The data can be written in several steps but you will have to compute
- * the total size up front for the invocation of dasd_eer_start_record.
- * If the ringbuffer is full, dasd_eer_start_record will remove the required
- * number of old records.
- *
- * A record is typically read in two steps, first read the integer that
- * specifies the size of the following data, then read the data.
- * Both can be done by
- * - dasd_eer_read_buffer
- *
- * For all mentioned functions you need to get the bufferlock first and keep it
- * until a complete record is written or read.
- */
-
-
-/*
- * Alle information necessary to keep track of an internal buffer is kept in
- * a struct eerbuffer. The buffer specific to a file pointer is strored in
- * the private_data field of that file. To be able to write data to all
- * existing buffers, each buffer is also added to the bufferlist.
- * If the user doesn't want to read a complete record in one go, we have to
- * keep track of the rest of the record. residual stores the number of bytes
- * that are still to deliver. If the rest of the record is invalidated between
- * two reads then residual will be set to -1 so that the next read will fail.
- * All entries in the eerbuffer structure are protected with the bufferlock.
- * To avoid races between writing to a buffer on the one side and creating
- * and destroying buffers on the other side, the bufferlock must also be used
- * to protect the bufferlist.
- */
-
-struct eerbuffer {
- struct list_head list;
- char **buffer;
- int buffersize;
- int buffer_page_count;
- int head;
- int tail;
- int residual;
-};
-
-LIST_HEAD(bufferlist);
-
-static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED;
-
-DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue);
-
-/*
- * How many free bytes are available on the buffer.
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_get_free_bytes(struct eerbuffer *eerb)
-{
- if (eerb->head < eerb->tail) {
- return eerb->tail - eerb->head - 1;
- } else
- return eerb->buffersize - eerb->head + eerb->tail -1;
-}
-
-/*
- * How many bytes of buffer space are used.
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_get_filled_bytes(struct eerbuffer *eerb)
-{
-
- if (eerb->head >= eerb->tail) {
- return eerb->head - eerb->tail;
- } else
- return eerb->buffersize - eerb->tail + eerb->head;
-}
-
-/*
- * The dasd_eer_write_buffer function just copies count bytes of data
- * to the buffer. Make sure to call dasd_eer_start_record first, to
- * make sure that enough free space is available.
- * needs to be called with bufferlock held
- */
-static void
-dasd_eer_write_buffer(struct eerbuffer *eerb, int count, char *data)
-{
-
- unsigned long headindex,localhead;
- unsigned long rest, len;
- char *nextdata;
-
- nextdata = data;
- rest = count;
- while (rest > 0) {
- headindex = eerb->head / PAGE_SIZE;
- localhead = eerb->head % PAGE_SIZE;
- len = min(rest, (PAGE_SIZE - localhead));
- memcpy(eerb->buffer[headindex]+localhead, nextdata, len);
- nextdata += len;
- rest -= len;
- eerb->head += len;
- if ( eerb->head == eerb->buffersize )
- eerb->head = 0; /* wrap around */
- if (eerb->head > eerb->buffersize) {
- MESSAGE(KERN_ERR, "%s", "runaway buffer head.");
- BUG();
- }
- }
-}
-
-/*
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_read_buffer(struct eerbuffer *eerb, int count, char *data)
-{
-
- unsigned long tailindex,localtail;
- unsigned long rest, len, finalcount;
- char *nextdata;
-
- finalcount = min(count, dasd_eer_get_filled_bytes(eerb));
- nextdata = data;
- rest = finalcount;
- while (rest > 0) {
- tailindex = eerb->tail / PAGE_SIZE;
- localtail = eerb->tail % PAGE_SIZE;
- len = min(rest, (PAGE_SIZE - localtail));
- memcpy(nextdata, eerb->buffer[tailindex]+localtail, len);
- nextdata += len;
- rest -= len;
- eerb->tail += len;
- if ( eerb->tail == eerb->buffersize )
- eerb->tail = 0; /* wrap around */
- if (eerb->tail > eerb->buffersize) {
- MESSAGE(KERN_ERR, "%s", "runaway buffer tail.");
- BUG();
- }
- }
- return finalcount;
-}
-
-/*
- * Whenever you want to write a blob of data to the internal buffer you
- * have to start by using this function first. It will write the number
- * of bytes that will be written to the buffer. If necessary it will remove
- * old records to make room for the new one.
- * needs to be called with bufferlock held
- */
-static int
-dasd_eer_start_record(struct eerbuffer *eerb, int count)
-{
- int tailcount;
- if (count + sizeof(count) > eerb->buffersize)
- return -ENOMEM;
- while (dasd_eer_get_free_bytes(eerb) < count + sizeof(count)) {
- if (eerb->residual > 0) {
- eerb->tail += eerb->residual;
- if (eerb->tail >= eerb->buffersize)
- eerb->tail -= eerb->buffersize;
- eerb->residual = -1;
- }
- dasd_eer_read_buffer(eerb, sizeof(tailcount),
- (char*)(&tailcount));
- eerb->tail += tailcount;
- if (eerb->tail >= eerb->buffersize)
- eerb->tail -= eerb->buffersize;
- }
- dasd_eer_write_buffer(eerb, sizeof(count), (char*)(&count));
-
- return 0;
-};
-
-/*
- * release pages that are not used anymore
- */
-static void
-dasd_eer_free_buffer_pages(char **buf, int no_pages)
-{
- int i;
-
- for (i = 0; i < no_pages; ++i) {
- free_page((unsigned long)buf[i]);
- }
-}
-
-/*
- * allocate a new set of memory pages
- */
-static int
-dasd_eer_allocate_buffer_pages(char **buf, int no_pages)
-{
- int i;
-
- for (i = 0; i < no_pages; ++i) {
- buf[i] = (char *) get_zeroed_page(GFP_KERNEL);
- if (!buf[i]) {
- dasd_eer_free_buffer_pages(buf, i);
- return -ENOMEM;
- }
- }
- return 0;
-}
-
-/*
- * empty the buffer by resetting head and tail
- * In case there is a half read data blob in the buffer, we set residual
- * to -1 to indicate that the remainder of the blob is lost.
- */
-static void
-dasd_eer_purge_buffer(struct eerbuffer *eerb)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&bufferlock, flags);
- if (eerb->residual > 0)
- eerb->residual = -1;
- eerb->tail=0;
- eerb->head=0;
- spin_unlock_irqrestore(&bufferlock, flags);
-}
-
-/*
- * set the size of the buffer, newsize is the new number of pages to be used
- * we don't try to copy any data back an forth, so any resize will also purge
- * the buffer
- */
-static int
-dasd_eer_resize_buffer(struct eerbuffer *eerb, int newsize)
-{
- int i, oldcount, reuse;
- char **new;
- char **old;
- unsigned long flags;
-
- if (newsize < 1)
- return -EINVAL;
- if (eerb->buffer_page_count == newsize) {
- /* documented behaviour is that any successfull invocation
- * will purge all records */
- dasd_eer_purge_buffer(eerb);
- return 0;
- }
- new = kmalloc(newsize*sizeof(char*), GFP_KERNEL);
- if (!new)
- return -ENOMEM;
-
- reuse=min(eerb->buffer_page_count, newsize);
- for (i = 0; i < reuse; ++i) {
- new[i] = eerb->buffer[i];
- }
- if (eerb->buffer_page_count < newsize) {
- if (dasd_eer_allocate_buffer_pages(
- &new[eerb->buffer_page_count],
- newsize - eerb->buffer_page_count)) {
- kfree(new);
- return -ENOMEM;
- }
- }
-
- spin_lock_irqsave(&bufferlock, flags);
- old = eerb->buffer;
- eerb->buffer = new;
- if (eerb->residual > 0)
- eerb->residual = -1;
- eerb->tail = 0;
- eerb->head = 0;
- oldcount = eerb->buffer_page_count;
- eerb->buffer_page_count = newsize;
- spin_unlock_irqrestore(&bufferlock, flags);
-
- if (oldcount > newsize) {
- for (i = newsize; i < oldcount; ++i) {
- free_page((unsigned long)old[i]);
- }
- }
- kfree(old);
-
- return 0;
-}
-
-
-/*****************************************************************************/
-/* The extended error reporting functionality */
-/*****************************************************************************/
-
-/*
- * When a DASD device driver wants to report an error, it calls the
- * function dasd_eer_write_trigger (via a notifier mechanism) and gives the
- * respective trigger ID as parameter.
- * Currently there are four kinds of triggers:
- *
- * DASD_EER_FATALERROR: all kinds of unrecoverable I/O problems
- * DASD_EER_PPRCSUSPEND: PPRC was suspended
- * DASD_EER_NOPATH: There is no path to the device left.
- * DASD_EER_STATECHANGE: The state of the device has changed.
- *
- * For the first three triggers all required information can be supplied by
- * the caller. For these triggers a record is written by the function
- * dasd_eer_write_standard_trigger.
- *
- * When dasd_eer_write_trigger is called to write a DASD_EER_STATECHANGE
- * trigger, we have to gather the necessary sense data first. We cannot queue
- * the necessary SNSS (sense subsystem status) request immediatly, since we
- * are likely to run in a deadlock situation. Instead, we schedule a
- * work_struct that calls the function dasd_eer_sense_subsystem_status to
- * create and start an SNSS request asynchronously.
- *
- * To avoid memory allocations at runtime, the necessary memory is allocated
- * when the extended error reporting is enabled for a device (by
- * dasd_eer_probe). There is one private eer data structure for each eer
- * enabled DASD device. It contains memory for the work_struct, one SNSS cqr
- * and a flags field that is used to coordinate the use of the cqr. The call
- * to write a state change trigger can come in at any time, so we have one flag
- * CQR_IN_USE that protects the cqr itself. When this flag indicates that the
- * cqr is currently in use, dasd_eer_sense_subsystem_status cannot start a
- * second request but sets the SNSS_REQUESTED flag instead.
- *
- * When the request is finished, the callback function dasd_eer_SNSS_cb
- * is called. This function will invoke the function
- * dasd_eer_write_SNSS_trigger to finally write the trigger. It will also
- * check the SNSS_REQUESTED flag and if it is set it will call
- * dasd_eer_sense_subsystem_status again.
- *
- * To avoid race conditions during the handling of the lock, the flags must
- * be protected by the snsslock.
- */
-
-struct dasd_eer_private {
- struct dasd_ccw_req *cqr;
- unsigned long flags;
- struct work_struct worker;
-};
-
-static void dasd_eer_destroy(struct dasd_device *device,
- struct dasd_eer_private *eer);
-static int
-dasd_eer_write_trigger(struct dasd_eer_trigger *trigger);
-static void dasd_eer_sense_subsystem_status(void *data);
-static int dasd_eer_notify(struct notifier_block *self,
- unsigned long action, void *data);
-
-struct workqueue_struct *dasd_eer_workqueue;
-
-#define SNSS_DATA_SIZE 44
-static spinlock_t snsslock = SPIN_LOCK_UNLOCKED;
-
-#define DASD_EER_BUSID_SIZE 10
-struct dasd_eer_header {
- __u32 total_size;
- __u32 trigger;
- __u64 tv_sec;
- __u64 tv_usec;
- char busid[DASD_EER_BUSID_SIZE];
-} __attribute__ ((packed));
-
-static struct notifier_block dasd_eer_nb = {
- .notifier_call = dasd_eer_notify,
-};
-
-/*
- * flags for use with dasd_eer_private
- */
-#define CQR_IN_USE 0
-#define SNSS_REQUESTED 1
-
-/*
- * This function checks if extended error reporting is available for a given
- * dasd_device. If yes, then it creates and returns a struct dasd_eer,
- * otherwise it returns an -EPERM error pointer.
- */
-struct dasd_eer_private *
-dasd_eer_probe(struct dasd_device *device)
-{
- struct dasd_eer_private *private;
-
- if (!(device && device->discipline
- && !strcmp(device->discipline->name, "ECKD"))) {
- return ERR_PTR(-EPERM);
- }
- /* allocate the private data structure */
- private = (struct dasd_eer_private *)kmalloc(
- sizeof(struct dasd_eer_private), GFP_KERNEL);
- if (!private) {
- return ERR_PTR(-ENOMEM);
- }
- INIT_WORK(&private->worker, dasd_eer_sense_subsystem_status,
- (void *)device);
- private->cqr = dasd_kmalloc_request("ECKD",
- 1 /* SNSS */ ,
- SNSS_DATA_SIZE ,
- device);
- if (!private->cqr) {
- kfree(private);
- return ERR_PTR(-ENOMEM);
- }
- private->flags = 0;
- return private;
-};
-
-/*
- * If our private SNSS request is queued, remove it from the
- * dasd ccw queue so we can free the requests memory.
- */
-static void
-dasd_eer_dequeue_SNSS_request(struct dasd_device *device,
- struct dasd_eer_private *eer)
-{
- struct list_head *lst, *nxt;
- struct dasd_ccw_req *cqr, *erpcqr;
- dasd_erp_fn_t erp_fn;
-
- spin_lock_irq(get_ccwdev_lock(device->cdev));
- list_for_each_safe(lst, nxt, &device->ccw_queue) {
- cqr = list_entry(lst, struct dasd_ccw_req, list);
- /* we are looking for two kinds or requests */
- /* first kind: our SNSS request: */
- if (cqr == eer->cqr) {
- if (cqr->status == DASD_CQR_IN_IO)
- device->discipline->term_IO(cqr);
- list_del(&cqr->list);
- break;
- }
- /* second kind: ERP requests for our SNSS request */
- if (cqr->refers) {
- /* If this erp request chain ends in our cqr, then */
- /* cal the erp_postaction to clean it up */
- erpcqr = cqr;
- while (erpcqr->refers) {
- erpcqr = erpcqr->refers;
- }
- if (erpcqr == eer->cqr) {
- erp_fn = device->discipline->erp_postaction(
- cqr);
- erp_fn(cqr);
- }
- continue;
- }
- }
- spin_unlock_irq(get_ccwdev_lock(device->cdev));
-}
-
-/*
- * This function dismantles a struct dasd_eer that was created by
- * dasd_eer_probe. Since we want to free our private data structure,
- * we must make sure that the memory is not in use anymore.
- * We have to flush the work queue and remove a possible SNSS request
- * from the dasd queue.
- */
-static void
-dasd_eer_destroy(struct dasd_device *device, struct dasd_eer_private *eer)
-{
- flush_workqueue(dasd_eer_workqueue);
- dasd_eer_dequeue_SNSS_request(device, eer);
- dasd_kfree_request(eer->cqr, device);
- kfree(eer);
-};
-
-/*
- * enable the extended error reporting for a particular device
- */
-static int
-dasd_eer_enable_on_device(struct dasd_device *device)
-{
- void *eer;
- if (!device)
- return -ENODEV;
- if (device->eer)
- return 0;
- if (!try_module_get(THIS_MODULE)) {
- return -EINVAL;
- }
- eer = (void *)dasd_eer_probe(device);
- if (IS_ERR(eer)) {
- module_put(THIS_MODULE);
- return PTR_ERR(eer);
- }
- device->eer = eer;
- return 0;
-}
-
-/*
- * enable the extended error reporting for a particular device
- */
-static int
-dasd_eer_disable_on_device(struct dasd_device *device)
-{
- struct dasd_eer_private *eer = device->eer;
-
- if (!device)
- return -ENODEV;
- if (!device->eer)
- return 0;
- device->eer = NULL;
- dasd_eer_destroy(device,eer);
- module_put(THIS_MODULE);
-
- return 0;
-}
-
-/*
- * Set extended error reporting (eer)
- * Note: This will be registered as a DASD ioctl, to be called on DASD devices.
- */
-static int
-dasd_ioctl_set_eer(struct block_device *bdev, int no, long args)
-{
- struct dasd_device *device;
- int intval;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (bdev != bdev->bd_contains)
- /* Error-reporting is not allowed for partitions */
- return -EINVAL;
- if (get_user(intval, (int __user *) args))
- return -EFAULT;
- device = bdev->bd_disk->private_data;
- if (device == NULL)
- return -ENODEV;
-
- intval = (intval != 0);
- DEV_MESSAGE (KERN_DEBUG, device,
- "set eer on device to %d", intval);
- if (intval)
- return dasd_eer_enable_on_device(device);
- else
- return dasd_eer_disable_on_device(device);
-}
-
-/*
- * Get value of extended error reporting.
- * Note: This will be registered as a DASD ioctl, to be called on DASD devices.
- */
-static int
-dasd_ioctl_get_eer(struct block_device *bdev, int no, long args)
-{
- struct dasd_device *device;
-
- device = bdev->bd_disk->private_data;
- if (device == NULL)
- return -ENODEV;
- return put_user((device->eer != NULL), (int __user *) args);
-}
-
-/*
- * The following function can be used for those triggers that have
- * all necessary data available when the function is called.
- * If the parameter cqr is not NULL, the chain of requests will be searched
- * for valid sense data, and all valid sense data sets will be added to
- * the triggers data.
- */
-static int
-dasd_eer_write_standard_trigger(int trigger, struct dasd_device *device,
- struct dasd_ccw_req *cqr)
-{
- struct dasd_ccw_req *temp_cqr;
- int data_size;
- struct timeval tv;
- struct dasd_eer_header header;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- /* go through cqr chain and count the valid sense data sets */
- temp_cqr = cqr;
- data_size = 0;
- while (temp_cqr) {
- if (temp_cqr->irb.esw.esw0.erw.cons)
- data_size += 32;
- temp_cqr = temp_cqr->refers;
- }
-
- header.total_size = sizeof(header) + data_size + 4; /* "EOR" */
- header.trigger = trigger;
- do_gettimeofday(&tv);
- header.tv_sec = tv.tv_sec;
- header.tv_usec = tv.tv_usec;
- strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
-
- spin_lock_irqsave(&bufferlock, flags);
- list_for_each_entry(eerb, &bufferlist, list) {
- dasd_eer_start_record(eerb, header.total_size);
- dasd_eer_write_buffer(eerb, sizeof(header), (char*)(&header));
- temp_cqr = cqr;
- while (temp_cqr) {
- if (temp_cqr->irb.esw.esw0.erw.cons)
- dasd_eer_write_buffer(eerb, 32, cqr->irb.ecw);
- temp_cqr = temp_cqr->refers;
- }
- dasd_eer_write_buffer(eerb, 4,"EOR");
- }
- spin_unlock_irqrestore(&bufferlock, flags);
-
- wake_up_interruptible(&dasd_eer_read_wait_queue);
-
- return 0;
-}
-
-/*
- * This function writes a DASD_EER_STATECHANGE trigger.
- */
-static void
-dasd_eer_write_SNSS_trigger(struct dasd_device *device,
- struct dasd_ccw_req *cqr)
-{
- int data_size;
- int snss_rc;
- struct timeval tv;
- struct dasd_eer_header header;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- snss_rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0;
- if (snss_rc)
- data_size = 0;
- else
- data_size = SNSS_DATA_SIZE;
-
- header.total_size = sizeof(header) + data_size + 4; /* "EOR" */
- header.trigger = DASD_EER_STATECHANGE;
- do_gettimeofday(&tv);
- header.tv_sec = tv.tv_sec;
- header.tv_usec = tv.tv_usec;
- strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE);
-
- spin_lock_irqsave(&bufferlock, flags);
- list_for_each_entry(eerb, &bufferlist, list) {
- dasd_eer_start_record(eerb, header.total_size);
- dasd_eer_write_buffer(eerb, sizeof(header),(char*)(&header));
- if (!snss_rc)
- dasd_eer_write_buffer(eerb, SNSS_DATA_SIZE, cqr->data);
- dasd_eer_write_buffer(eerb, 4,"EOR");
- }
- spin_unlock_irqrestore(&bufferlock, flags);
-
- wake_up_interruptible(&dasd_eer_read_wait_queue);
-}
-
-/*
- * callback function for use with SNSS request
- */
-static void
-dasd_eer_SNSS_cb(struct dasd_ccw_req *cqr, void *data)
-{
- struct dasd_device *device;
- struct dasd_eer_private *private;
- unsigned long irqflags;
-
- device = (struct dasd_device *)data;
- private = (struct dasd_eer_private *)device->eer;
- dasd_eer_write_SNSS_trigger(device, cqr);
- spin_lock_irqsave(&snsslock, irqflags);
- if(!test_and_clear_bit(SNSS_REQUESTED, &private->flags)) {
- clear_bit(CQR_IN_USE, &private->flags);
- spin_unlock_irqrestore(&snsslock, irqflags);
- return;
- };
- clear_bit(CQR_IN_USE, &private->flags);
- spin_unlock_irqrestore(&snsslock, irqflags);
- dasd_eer_sense_subsystem_status(device);
- return;
-}
-
-/*
- * clean a used cqr before using it again
- */
-static void
-dasd_eer_clean_SNSS_request(struct dasd_ccw_req *cqr)
-{
- struct ccw1 *cpaddr = cqr->cpaddr;
- void *data = cqr->data;
-
- memset(cqr, 0, sizeof(struct dasd_ccw_req));
- memset(cpaddr, 0, sizeof(struct ccw1));
- memset(data, 0, SNSS_DATA_SIZE);
- cqr->cpaddr = cpaddr;
- cqr->data = data;
- strncpy((char *) &cqr->magic, "ECKD", 4);
- ASCEBC((char *) &cqr->magic, 4);
- set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
-}
-
-/*
- * build and start an SNSS request
- * This function is called from a work queue so we have to
- * pass the dasd_device pointer as a void pointer.
- */
-static void
-dasd_eer_sense_subsystem_status(void *data)
-{
- struct dasd_device *device;
- struct dasd_eer_private *private;
- struct dasd_ccw_req *cqr;
- struct ccw1 *ccw;
- unsigned long irqflags;
-
- device = (struct dasd_device *)data;
- private = (struct dasd_eer_private *)device->eer;
- if (!private) /* device not eer enabled any more */
- return;
- cqr = private->cqr;
- spin_lock_irqsave(&snsslock, irqflags);
- if(test_and_set_bit(CQR_IN_USE, &private->flags)) {
- set_bit(SNSS_REQUESTED, &private->flags);
- spin_unlock_irqrestore(&snsslock, irqflags);
- return;
- };
- spin_unlock_irqrestore(&snsslock, irqflags);
- dasd_eer_clean_SNSS_request(cqr);
- cqr->device = device;
- cqr->retries = 255;
- cqr->expires = 10 * HZ;
-
- ccw = cqr->cpaddr;
- ccw->cmd_code = DASD_ECKD_CCW_SNSS;
- ccw->count = SNSS_DATA_SIZE;
- ccw->flags = 0;
- ccw->cda = (__u32)(addr_t)cqr->data;
-
- cqr->buildclk = get_clock();
- cqr->status = DASD_CQR_FILLED;
- cqr->callback = dasd_eer_SNSS_cb;
- cqr->callback_data = (void *)device;
- dasd_add_request_head(cqr);
-
- return;
-}
-
-/*
- * This function is called for all triggers. It calls the appropriate
- * function that writes the actual trigger records.
- */
-static int
-dasd_eer_write_trigger(struct dasd_eer_trigger *trigger)
-{
- int rc;
- struct dasd_eer_private *private = trigger->device->eer;
-
- switch (trigger->id) {
- case DASD_EER_FATALERROR:
- case DASD_EER_PPRCSUSPEND:
- rc = dasd_eer_write_standard_trigger(
- trigger->id, trigger->device, trigger->cqr);
- break;
- case DASD_EER_NOPATH:
- rc = dasd_eer_write_standard_trigger(
- trigger->id, trigger->device, NULL);
- break;
- case DASD_EER_STATECHANGE:
- if (queue_work(dasd_eer_workqueue, &private->worker)) {
- rc=0;
- } else {
- /* If the work_struct was already queued, it can't
- * be queued again. But this is OK since we don't
- * need to have it queued twice.
- */
- rc = -EBUSY;
- }
- break;
- default: /* unknown trigger, so we write it without any sense data */
- rc = dasd_eer_write_standard_trigger(
- trigger->id, trigger->device, NULL);
- break;
- }
- return rc;
-}
-
-/*
- * This function is registered with the dasd device driver and gets called
- * for all dasd eer notifications.
- */
-static int dasd_eer_notify(struct notifier_block *self,
- unsigned long action, void *data)
-{
- switch (action) {
- case DASD_EER_DISABLE:
- dasd_eer_disable_on_device((struct dasd_device *)data);
- break;
- case DASD_EER_TRIGGER:
- dasd_eer_write_trigger((struct dasd_eer_trigger *)data);
- break;
- }
- return NOTIFY_OK;
-}
-
-
-/*****************************************************************************/
-/* the device operations */
-/*****************************************************************************/
-
-/*
- * On the one side we need a lock to access our internal buffer, on the
- * other side a copy_to_user can sleep. So we need to copy the data we have
- * to transfer in a readbuffer, which is protected by the readbuffer_mutex.
- */
-static char readbuffer[PAGE_SIZE];
-DECLARE_MUTEX(readbuffer_mutex);
-
-
-static int
-dasd_eer_open(struct inode *inp, struct file *filp)
-{
- struct eerbuffer *eerb;
- unsigned long flags;
-
- eerb = kmalloc(sizeof(struct eerbuffer), GFP_KERNEL);
- eerb->head = 0;
- eerb->tail = 0;
- eerb->residual = 0;
- eerb->buffer_page_count = 1;
- eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE;
- eerb->buffer = kmalloc(eerb->buffer_page_count*sizeof(char*),
- GFP_KERNEL);
- if (!eerb->buffer)
- return -ENOMEM;
- if (dasd_eer_allocate_buffer_pages(eerb->buffer,
- eerb->buffer_page_count)) {
- kfree(eerb->buffer);
- return -ENOMEM;
- }
- filp->private_data = eerb;
- spin_lock_irqsave(&bufferlock, flags);
- list_add(&eerb->list, &bufferlist);
- spin_unlock_irqrestore(&bufferlock, flags);
-
- return nonseekable_open(inp,filp);
-}
-
-static int
-dasd_eer_close(struct inode *inp, struct file *filp)
-{
- struct eerbuffer *eerb;
- unsigned long flags;
-
- eerb = (struct eerbuffer *)filp->private_data;
- spin_lock_irqsave(&bufferlock, flags);
- list_del(&eerb->list);
- spin_unlock_irqrestore(&bufferlock, flags);
- dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count);
- kfree(eerb->buffer);
- kfree(eerb);
-
- return 0;
-}
-
-static long
-dasd_eer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- int intval;
- struct eerbuffer *eerb;
-
- eerb = (struct eerbuffer *)filp->private_data;
- switch (cmd) {
- case DASD_EER_PURGE:
- dasd_eer_purge_buffer(eerb);
- return 0;
- case DASD_EER_SETBUFSIZE:
- if (get_user(intval, (int __user *)arg))
- return -EFAULT;
- return dasd_eer_resize_buffer(eerb, intval);
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-static ssize_t
-dasd_eer_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
-{
- int tc,rc;
- int tailcount,effective_count;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- eerb = (struct eerbuffer *)filp->private_data;
- if(down_interruptible(&readbuffer_mutex))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&bufferlock, flags);
-
- if (eerb->residual < 0) { /* the remainder of this record */
- /* has been deleted */
- eerb->residual = 0;
- spin_unlock_irqrestore(&bufferlock, flags);
- up(&readbuffer_mutex);
- return -EIO;
- } else if (eerb->residual > 0) {
- /* OK we still have a second half of a record to deliver */
- effective_count = min(eerb->residual, (int)count);
- eerb->residual -= effective_count;
- } else {
- tc = 0;
- while (!tc) {
- tc = dasd_eer_read_buffer(eerb,
- sizeof(tailcount), (char*)(&tailcount));
- if (!tc) {
- /* no data available */
- spin_unlock_irqrestore(&bufferlock, flags);
- up(&readbuffer_mutex);
- if (filp->f_flags & O_NONBLOCK)
- return -EAGAIN;
- rc = wait_event_interruptible(
- dasd_eer_read_wait_queue,
- eerb->head != eerb->tail);
- if (rc) {
- return rc;
- }
- if(down_interruptible(&readbuffer_mutex))
- return -ERESTARTSYS;
- spin_lock_irqsave(&bufferlock, flags);
- }
- }
- WARN_ON(tc != sizeof(tailcount));
- effective_count = min(tailcount,(int)count);
- eerb->residual = tailcount - effective_count;
- }
-
- tc = dasd_eer_read_buffer(eerb, effective_count, readbuffer);
- WARN_ON(tc != effective_count);
-
- spin_unlock_irqrestore(&bufferlock, flags);
-
- if (copy_to_user(buf, readbuffer, effective_count)) {
- up(&readbuffer_mutex);
- return -EFAULT;
- }
-
- up(&readbuffer_mutex);
- return effective_count;
-}
-
-static unsigned int
-dasd_eer_poll (struct file *filp, poll_table *ptable)
-{
- unsigned int mask;
- unsigned long flags;
- struct eerbuffer *eerb;
-
- eerb = (struct eerbuffer *)filp->private_data;
- poll_wait(filp, &dasd_eer_read_wait_queue, ptable);
- spin_lock_irqsave(&bufferlock, flags);
- if (eerb->head != eerb->tail)
- mask = POLLIN | POLLRDNORM ;
- else
- mask = 0;
- spin_unlock_irqrestore(&bufferlock, flags);
- return mask;
-}
-
-static struct file_operations dasd_eer_fops = {
- .open = &dasd_eer_open,
- .release = &dasd_eer_close,
- .unlocked_ioctl = &dasd_eer_ioctl,
- .compat_ioctl = &dasd_eer_ioctl,
- .read = &dasd_eer_read,
- .poll = &dasd_eer_poll,
- .owner = THIS_MODULE,
-};
-
-static struct miscdevice dasd_eer_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "dasd_eer",
- .fops = &dasd_eer_fops,
-};
-
-
-/*****************************************************************************/
-/* Init and exit */
-/*****************************************************************************/
-
-static int
-__init dasd_eer_init(void)
-{
- int rc;
-
- dasd_eer_workqueue = create_singlethread_workqueue("dasd_eer");
- if (!dasd_eer_workqueue) {
- MESSAGE(KERN_ERR , "%s", "dasd_eer_init could not "
- "create workqueue \n");
- rc = -ENOMEM;
- goto out;
- }
-
- rc = dasd_register_eer_notifier(&dasd_eer_nb);
- if (rc) {
- MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
- "register error reporting");
- goto queue;
- }
-
- dasd_ioctl_no_register(THIS_MODULE, BIODASDEERSET, dasd_ioctl_set_eer);
- dasd_ioctl_no_register(THIS_MODULE, BIODASDEERGET, dasd_ioctl_get_eer);
-
- /* we don't need our own character device,
- * so we just register as misc device */
- rc = misc_register(&dasd_eer_dev);
- if (rc) {
- MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
- "register misc device");
- goto unregister;
- }
-
- return 0;
-
-unregister:
- dasd_unregister_eer_notifier(&dasd_eer_nb);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET,
- dasd_ioctl_set_eer);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET,
- dasd_ioctl_get_eer);
-queue:
- destroy_workqueue(dasd_eer_workqueue);
-out:
- return rc;
-
-}
-module_init(dasd_eer_init);
-
-static void
-__exit dasd_eer_exit(void)
-{
- dasd_unregister_eer_notifier(&dasd_eer_nb);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET,
- dasd_ioctl_set_eer);
- dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET,
- dasd_ioctl_get_eer);
- destroy_workqueue(dasd_eer_workqueue);
-
- WARN_ON(misc_deregister(&dasd_eer_dev) != 0);
-}
-module_exit(dasd_eer_exit);
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index d1b08fa13fd224..0592354cc60431 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -275,34 +275,6 @@ struct dasd_discipline {
extern struct dasd_discipline *dasd_diag_discipline_pointer;
-
-/*
- * Notification numbers for extended error reporting notifications:
- * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's
- * eer pointer) is freed. The error reporting module needs to do all necessary
- * cleanup steps.
- * The DASD_EER_TRIGGER notification sends the actual error reports (triggers).
- */
-#define DASD_EER_DISABLE 0
-#define DASD_EER_TRIGGER 1
-
-/* Trigger IDs for extended error reporting DASD_EER_TRIGGER notification */
-#define DASD_EER_FATALERROR 1
-#define DASD_EER_NOPATH 2
-#define DASD_EER_STATECHANGE 3
-#define DASD_EER_PPRCSUSPEND 4
-
-/*
- * The dasd_eer_trigger structure contains all data that we need to send
- * along with an DASD_EER_TRIGGER notification.
- */
-struct dasd_eer_trigger {
- unsigned int id;
- struct dasd_device *device;
- struct dasd_ccw_req *cqr;
-};
-
-
struct dasd_device {
/* Block device stuff. */
struct gendisk *gdp;
@@ -316,11 +288,9 @@ struct dasd_device {
unsigned long flags; /* per device flags */
unsigned short features; /* copy of devmap-features (read-only!) */
- /* extended error reporting stuff (eer) */
- void *eer;
-
/* Device discipline stuff. */
struct dasd_discipline *discipline;
+ struct dasd_discipline *base_discipline;
char *private;
/* Device state and target state. */
@@ -519,12 +489,6 @@ int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *);
int dasd_generic_set_offline (struct ccw_device *cdev);
int dasd_generic_notify(struct ccw_device *, int);
void dasd_generic_auto_online (struct ccw_driver *);
-int dasd_register_eer_notifier(struct notifier_block *);
-int dasd_unregister_eer_notifier(struct notifier_block *);
-void dasd_write_eer_trigger(unsigned int , struct dasd_device *,
- struct dasd_ccw_req *);
-
-
/* externals in dasd_devmap.c */
extern int dasd_max_devindex;
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index ceb0e474fde469..4138564402b8c2 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -85,11 +85,10 @@ static volatile enum sclp_mask_state_t {
/* Maximum retry counts */
#define SCLP_INIT_RETRY 3
#define SCLP_MASK_RETRY 3
-#define SCLP_REQUEST_RETRY 3
/* Timeout intervals in seconds.*/
-#define SCLP_BUSY_INTERVAL 2
-#define SCLP_RETRY_INTERVAL 5
+#define SCLP_BUSY_INTERVAL 10
+#define SCLP_RETRY_INTERVAL 15
static void sclp_process_queue(void);
static int sclp_init_mask(int calculate);
@@ -153,11 +152,9 @@ __sclp_start_request(struct sclp_req *req)
if (sclp_running_state != sclp_running_state_idle)
return 0;
del_timer(&sclp_request_timer);
- if (req->start_count <= SCLP_REQUEST_RETRY) {
- rc = service_call(req->command, req->sccb);
- req->start_count++;
- } else
- rc = -EIO;
+ rc = service_call(req->command, req->sccb);
+ req->start_count++;
+
if (rc == 0) {
/* Sucessfully started request */
req->status = SCLP_REQ_RUNNING;
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 92be75d99a56eb..8cf9905d484be5 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -232,7 +232,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
return 0;
mask = 0x80 >> j;
- spin_lock(&sch->lock);
+ spin_lock_irq(&sch->lock);
stsch(sch->schid, &schib);
if (!schib.pmcw.dnv)
@@ -281,10 +281,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
if (sch->driver && sch->driver->verify)
sch->driver->verify(&sch->dev);
out_unlock:
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
out_unreg:
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
sch->lpm = 0;
if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
@@ -652,7 +652,7 @@ __chp_add(struct subchannel_id schid, void *data)
if (!sch)
/* Check if the subchannel is now available. */
return __chp_add_new_sch(schid);
- spin_lock(&sch->lock);
+ spin_lock_irq(&sch->lock);
for (i=0; i<8; i++)
if (sch->schib.pmcw.chpid[i] == chp->id) {
if (stsch(sch->schid, &sch->schib) != 0) {
@@ -674,7 +674,7 @@ __chp_add(struct subchannel_id schid, void *data)
if (sch->driver && sch->driver->verify)
sch->driver->verify(&sch->dev);
- spin_unlock(&sch->lock);
+ spin_unlock_irq(&sch->lock);
put_device(&sch->dev);
return 0;
}
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 062fb100d94c17..afc4e88551ad2e 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -359,7 +359,7 @@ ccw_device_set_online(struct ccw_device *cdev)
else
pr_debug("ccw_device_offline returned %d, device %s\n",
ret, cdev->dev.bus_id);
- return (ret = 0) ? -ENODEV : ret;
+ return (ret == 0) ? -ENODEV : ret;
}
static ssize_t
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index d2a5b04d7cbab2..85b1020a1fcce5 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -405,7 +405,7 @@ __ccw_device_disband_start(struct ccw_device *cdev)
cdev->private->iretry = 5;
cdev->private->imask >>= 1;
}
- ccw_device_verify_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV);
+ ccw_device_disband_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV);
}
/*
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index dad4dd9887c9ea..6c762b43f921cf 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -317,7 +317,6 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
/*
* We have ending status but no sense information. Do a basic sense.
*/
- sch = to_subchannel(cdev->dev.parent);
sch->sense_ccw.cmd_code = CCW_CMD_BASIC_SENSE;
sch->sense_ccw.cda = (__u32) __pa(cdev->private->irb.ecw);
sch->sense_ccw.count = SENSE_MAX_COUNT;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 45ce032772f4e6..9ed37dc9a1b048 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -165,8 +165,13 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
q_no = q->q_no;
if(!q->is_input_q)
q_no += irq->no_input_qs;
+again:
ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt);
rc = qdio_check_ccq(q, ccq);
+ if (rc == 1) {
+ QDIO_DBF_TEXT5(1,trace,"eqAGAIN");
+ goto again;
+ }
if (rc < 0) {
QDIO_DBF_TEXT2(1,trace,"eqberr");
sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt, *cnt, ccq, q_no);
@@ -195,8 +200,13 @@ qdio_do_sqbs(struct qdio_q *q, unsigned char state,
q_no = q->q_no;
if(!q->is_input_q)
q_no += irq->no_input_qs;
+again:
ccq = do_sqbs(irq->sch_token, state, q_no, start, cnt);
rc = qdio_check_ccq(q, ccq);
+ if (rc == 1) {
+ QDIO_DBF_TEXT5(1,trace,"sqAGAIN");
+ goto again;
+ }
if (rc < 0) {
QDIO_DBF_TEXT3(1,trace,"sqberr");
sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no);
@@ -1187,8 +1197,7 @@ tiqdio_is_inbound_q_done(struct qdio_q *q)
if (!no_used)
return 1;
-
- if (!q->siga_sync)
+ if (!q->siga_sync && !irq->is_qebsm)
/* we'll check for more primed buffers in qeth_stop_polling */
return 0;
if (irq->is_qebsm) {
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 6229ba4995ad0e..9cf88d7201d38b 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -98,9 +98,9 @@ lcs_register_debug_facility(void)
return -ENOMEM;
}
debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view);
- debug_set_level(lcs_dbf_setup, 4);
+ debug_set_level(lcs_dbf_setup, 2);
debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view);
- debug_set_level(lcs_dbf_trace, 4);
+ debug_set_level(lcs_dbf_trace, 2);
return 0;
}
@@ -1292,9 +1292,8 @@ lcs_set_multicast_list(struct net_device *dev)
LCS_DBF_TEXT(4, trace, "setmulti");
card = (struct lcs_card *) dev->priv;
- if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) {
+ if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD))
schedule_work(&card->kernel_thread_starter);
- }
}
#endif /* CONFIG_IP_MULTICAST */
@@ -1459,6 +1458,8 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer)
lcs_release_buffer(channel, buffer);
card = (struct lcs_card *)
((char *) channel - offsetof(struct lcs_card, write));
+ if (netif_queue_stopped(card->dev))
+ netif_wake_queue(card->dev);
spin_lock(&card->lock);
card->tx_emitted--;
if (card->tx_emitted <= 0 && card->tx_buffer != NULL)
@@ -1478,6 +1479,7 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
struct net_device *dev)
{
struct lcs_header *header;
+ int rc = 0;
LCS_DBF_TEXT(5, trace, "hardxmit");
if (skb == NULL) {
@@ -1492,10 +1494,8 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
card->stats.tx_carrier_errors++;
return 0;
}
- if (netif_queue_stopped(dev) ) {
- card->stats.tx_dropped++;
- return -EBUSY;
- }
+ netif_stop_queue(card->dev);
+ spin_lock(&card->lock);
if (card->tx_buffer != NULL &&
card->tx_buffer->count + sizeof(struct lcs_header) +
skb->len + sizeof(u16) > LCS_IOBUFFERSIZE)
@@ -1506,7 +1506,8 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
card->tx_buffer = lcs_get_buffer(&card->write);
if (card->tx_buffer == NULL) {
card->stats.tx_dropped++;
- return -EBUSY;
+ rc = -EBUSY;
+ goto out;
}
card->tx_buffer->callback = lcs_txbuffer_cb;
card->tx_buffer->count = 0;
@@ -1518,13 +1519,18 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
header->type = card->lan_type;
header->slot = card->portno;
memcpy(header + 1, skb->data, skb->len);
+ spin_unlock(&card->lock);
card->stats.tx_bytes += skb->len;
card->stats.tx_packets++;
dev_kfree_skb(skb);
- if (card->tx_emitted <= 0)
+ netif_wake_queue(card->dev);
+ spin_lock(&card->lock);
+ if (card->tx_emitted <= 0 && card->tx_buffer != NULL)
/* If this is the first tx buffer emit it immediately. */
__lcs_emit_txbuffer(card);
- return 0;
+out:
+ spin_unlock(&card->lock);
+ return rc;
}
static int
@@ -1535,9 +1541,7 @@ lcs_start_xmit(struct sk_buff *skb, struct net_device *dev)
LCS_DBF_TEXT(5, trace, "pktxmit");
card = (struct lcs_card *) dev->priv;
- spin_lock(&card->lock);
rc = __lcs_start_xmit(card, skb, dev);
- spin_unlock(&card->lock);
return rc;
}
@@ -2319,7 +2323,6 @@ __init lcs_init_module(void)
PRINT_ERR("Initialization failed\n");
return rc;
}
-
return 0;
}
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 08e60ad439167e..2fad5e40c2e4e7 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -95,7 +95,7 @@ do { \
*/
#define LCS_ILLEGAL_OFFSET 0xffff
#define LCS_IOBUFFERSIZE 0x5000
-#define LCS_NUM_BUFFS 8 /* needs to be power of 2 */
+#define LCS_NUM_BUFFS 32 /* needs to be power of 2 */
#define LCS_MAC_LENGTH 6
#define LCS_INVALID_PORT_NO -1
#define LCS_LANCMD_TIMEOUT_DEFAULT 5
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 9a064d4727ad19..4df0fcd7b10b18 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -1076,16 +1076,6 @@ qeth_get_qdio_q_format(struct qeth_card *card)
}
static inline int
-qeth_isdigit(char * buf)
-{
- while (*buf) {
- if (!isdigit(*buf++))
- return 0;
- }
- return 1;
-}
-
-static inline int
qeth_isxdigit(char * buf)
{
while (*buf) {
@@ -1104,33 +1094,17 @@ qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
static inline int
qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
{
- const char *start, *end;
- char abuf[4];
- char *tmp;
- int len;
- int i;
-
- start = buf;
- for (i = 0; i < 4; i++) {
- if (i == 3) {
- end = strchr(start,0xa);
- if (end)
- len = end - start;
- else
- len = strlen(start);
- }
- else {
- end = strchr(start, '.');
- len = end - start;
- }
- if ((len <= 0) || (len > 3))
- return -EINVAL;
- memset(abuf, 0, 4);
- strncpy(abuf, start, len);
- if (!qeth_isdigit(abuf))
+ int count = 0, rc = 0;
+ int in[4];
+
+ rc = sscanf(buf, "%d.%d.%d.%d%n",
+ &in[0], &in[1], &in[2], &in[3], &count);
+ if (rc != 4 || count)
+ return -EINVAL;
+ for (count = 0; count < 4; count++) {
+ if (in[count] > 255)
return -EINVAL;
- addr[i] = simple_strtoul(abuf, &tmp, 10);
- start = end + 1;
+ addr[count] = in[count];
}
return 0;
}
@@ -1149,36 +1123,44 @@ qeth_ipaddr6_to_string(const __u8 *addr, char *buf)
static inline int
qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
{
- const char *start, *end;
- u16 *tmp_addr;
- char abuf[5];
- char *tmp;
- int len;
- int i;
-
- tmp_addr = (u16 *)addr;
- start = buf;
- for (i = 0; i < 8; i++) {
- if (i == 7) {
- end = strchr(start,0xa);
- if (end)
- len = end - start;
- else
- len = strlen(start);
- }
- else {
- end = strchr(start, ':');
- len = end - start;
+ char *end, *start;
+ __u16 *in;
+ char num[5];
+ int num2, cnt, out, found, save_cnt;
+ unsigned short in_tmp[8] = {0, };
+
+ cnt = out = found = save_cnt = num2 = 0;
+ end = start = (char *) buf;
+ in = (__u16 *) addr;
+ memset(in, 0, 16);
+ while (end) {
+ end = strchr(end,':');
+ if (end == NULL) {
+ end = (char *)buf + (strlen(buf));
+ out = 1;
+ }
+ if ((end - start)) {
+ memset(num, 0, 5);
+ memcpy(num, start, end - start);
+ if (!qeth_isxdigit(num))
+ return -EINVAL;
+ sscanf(start, "%x", &num2);
+ if (found)
+ in_tmp[save_cnt++] = num2;
+ else
+ in[cnt++] = num2;
+ if (out)
+ break;
+ } else {
+ if (found)
+ return -EINVAL;
+ found = 1;
}
- if ((len <= 0) || (len > 4))
- return -EINVAL;
- memset(abuf, 0, 5);
- strncpy(abuf, start, len);
- if (!qeth_isxdigit(abuf))
- return -EINVAL;
- tmp_addr[i] = simple_strtoul(abuf, &tmp, 16);
- start = end + 1;
- }
+ start = ++end;
+ }
+ cnt = 7;
+ while (save_cnt)
+ in[cnt--] = in_tmp[--save_cnt];
return 0;
}
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index b023131277807f..82cb4af2f0e700 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -59,8 +59,7 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx)
for (i = 0; i < ctx->num_pages; ++i)
free_page((unsigned long)ctx->pages[i]);
kfree(ctx->pages);
- if (ctx->elements != NULL)
- kfree(ctx->elements);
+ kfree(ctx->elements);
kfree(ctx);
}
@@ -413,6 +412,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
QETH_DBF_TEXT(trace, 5, "eddpftcp");
eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
+ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+ eddp->skb_offset += sizeof(struct ethhdr);
+#ifdef CONFIG_QETH_VLAN
+ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+ eddp->skb_offset += VLAN_HLEN;
+#endif /* CONFIG_QETH_VLAN */
+ }
tcph = eddp->skb->h.th;
while (eddp->skb_offset < eddp->skb->len) {
data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
@@ -483,6 +489,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
return -ENOMEM;
}
if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+ skb->mac.raw = (skb->data) + sizeof(struct qeth_hdr);
memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
#ifdef CONFIG_QETH_VLAN
if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 410abeada6c499..dba7f7f02e7949 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -516,7 +516,8 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
QETH_DBF_TEXT(setup, 3, "setoffl");
QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
- netif_carrier_off(card->dev);
+ if (card->dev && netif_carrier_ok(card->dev))
+ netif_carrier_off(card->dev);
recover_flag = card->state;
if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
PRINT_WARN("Stopping card %s interrupted by user!\n",
@@ -1679,6 +1680,7 @@ qeth_cmd_timeout(unsigned long data)
spin_unlock_irqrestore(&reply->card->lock, flags);
}
+
static struct qeth_ipa_cmd *
qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
{
@@ -1699,7 +1701,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
QETH_CARD_IFNAME(card),
card->info.chpid);
card->lan_online = 0;
- netif_carrier_off(card->dev);
+ if (card->dev && netif_carrier_ok(card->dev))
+ netif_carrier_off(card->dev);
return NULL;
case IPA_CMD_STARTLAN:
PRINT_INFO("Link reestablished on %s "
@@ -5562,7 +5565,7 @@ qeth_set_multicast_list(struct net_device *dev)
if (card->info.type == QETH_CARD_TYPE_OSN)
return ;
- QETH_DBF_TEXT(trace,3,"setmulti");
+ QETH_DBF_TEXT(trace, 3, "setmulti");
qeth_delete_mc_addresses(card);
if (card->options.layer2) {
qeth_layer2_add_multicast(card);
@@ -5579,7 +5582,6 @@ out:
return;
if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
schedule_work(&card->kernel_thread_starter);
-
}
static int
@@ -7452,6 +7454,7 @@ qeth_softsetup_card(struct qeth_card *card)
card->lan_online = 1;
if (card->info.type==QETH_CARD_TYPE_OSN)
goto out;
+ qeth_set_large_send(card, card->options.large_send);
if (card->options.layer2) {
card->dev->features |=
NETIF_F_HW_VLAN_FILTER |
@@ -7468,12 +7471,6 @@ qeth_softsetup_card(struct qeth_card *card)
#endif
goto out;
}
- if ((card->options.large_send == QETH_LARGE_SEND_EDDP) ||
- (card->options.large_send == QETH_LARGE_SEND_TSO))
- card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
- else
- card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
-
if ((rc = qeth_setadapter_parms(card)))
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
if ((rc = qeth_start_ipassists(card)))
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 4d7d47cf2394a3..a5f2ba9a8fdb57 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -710,10 +710,9 @@ static inline void
_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
struct zfcp_adapter *adapter,
struct scsi_cmnd *scsi_cmnd,
- struct zfcp_fsf_req *new_fsf_req)
+ struct zfcp_fsf_req *fsf_req,
+ struct zfcp_fsf_req *old_fsf_req)
{
- struct zfcp_fsf_req *fsf_req =
- (struct zfcp_fsf_req *)scsi_cmnd->host_scribble;
struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
unsigned long flags;
@@ -727,19 +726,20 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
if (offset == 0) {
strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
- if (scsi_cmnd->device) {
- rec->scsi_id = scsi_cmnd->device->id;
- rec->scsi_lun = scsi_cmnd->device->lun;
+ if (scsi_cmnd != NULL) {
+ if (scsi_cmnd->device) {
+ rec->scsi_id = scsi_cmnd->device->id;
+ rec->scsi_lun = scsi_cmnd->device->lun;
+ }
+ rec->scsi_result = scsi_cmnd->result;
+ rec->scsi_cmnd = (unsigned long)scsi_cmnd;
+ rec->scsi_serial = scsi_cmnd->serial_number;
+ memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd,
+ min((int)scsi_cmnd->cmd_len,
+ ZFCP_DBF_SCSI_OPCODE));
+ rec->scsi_retries = scsi_cmnd->retries;
+ rec->scsi_allowed = scsi_cmnd->allowed;
}
- rec->scsi_result = scsi_cmnd->result;
- rec->scsi_cmnd = (unsigned long)scsi_cmnd;
- rec->scsi_serial = scsi_cmnd->serial_number;
- memcpy(rec->scsi_opcode,
- &scsi_cmnd->cmnd,
- min((int)scsi_cmnd->cmd_len,
- ZFCP_DBF_SCSI_OPCODE));
- rec->scsi_retries = scsi_cmnd->retries;
- rec->scsi_allowed = scsi_cmnd->allowed;
if (fsf_req != NULL) {
fcp_rsp = (struct fcp_rsp_iu *)
&(fsf_req->qtcb->bottom.io.fcp_rsp);
@@ -772,15 +772,8 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
rec->fsf_seqno = fsf_req->seq_no;
rec->fsf_issued = fsf_req->issued;
}
- if (new_fsf_req != NULL) {
- rec->type.new_fsf_req.fsf_reqid =
- (unsigned long)
- new_fsf_req;
- rec->type.new_fsf_req.fsf_seqno =
- new_fsf_req->seq_no;
- rec->type.new_fsf_req.fsf_issued =
- new_fsf_req->issued;
- }
+ rec->type.old_fsf_reqid =
+ (unsigned long) old_fsf_req;
} else {
strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
dump->total_size = buflen;
@@ -801,19 +794,21 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
inline void
zfcp_scsi_dbf_event_result(const char *tag, int level,
struct zfcp_adapter *adapter,
- struct scsi_cmnd *scsi_cmnd)
+ struct scsi_cmnd *scsi_cmnd,
+ struct zfcp_fsf_req *fsf_req)
{
- _zfcp_scsi_dbf_event_common("rslt",
- tag, level, adapter, scsi_cmnd, NULL);
+ _zfcp_scsi_dbf_event_common("rslt", tag, level,
+ adapter, scsi_cmnd, fsf_req, NULL);
}
inline void
zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
struct scsi_cmnd *scsi_cmnd,
- struct zfcp_fsf_req *new_fsf_req)
+ struct zfcp_fsf_req *new_fsf_req,
+ struct zfcp_fsf_req *old_fsf_req)
{
- _zfcp_scsi_dbf_event_common("abrt",
- tag, 1, adapter, scsi_cmnd, new_fsf_req);
+ _zfcp_scsi_dbf_event_common("abrt", tag, 1,
+ adapter, scsi_cmnd, new_fsf_req, old_fsf_req);
}
inline void
@@ -823,7 +818,7 @@ zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
struct zfcp_adapter *adapter = unit->port->adapter;
_zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
- tag, 1, adapter, scsi_cmnd, NULL);
+ tag, 1, adapter, scsi_cmnd, NULL, NULL);
}
static int
@@ -856,6 +851,10 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
rec->scsi_retries);
len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
rec->scsi_allowed);
+ if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
+ len += zfcp_dbf_view(out_buf + len, "old_fsf_reqid", "0x%0Lx",
+ rec->type.old_fsf_reqid);
+ }
len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
rec->fsf_reqid);
len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
@@ -883,21 +882,6 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
min((int)rec->type.fcp.sns_info_len,
ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
rec->type.fcp.sns_info_len);
- } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
- len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx",
- rec->type.new_fsf_req.fsf_reqid);
- len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x",
- rec->type.new_fsf_req.fsf_seqno);
- len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
- rec->type.new_fsf_req.fsf_issued);
- } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) ||
- (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) {
- len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx",
- rec->type.new_fsf_req.fsf_reqid);
- len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x",
- rec->type.new_fsf_req.fsf_seqno);
- len += zfcp_dbf_stck(out_buf + len, "fsf_issued",
- rec->type.new_fsf_req.fsf_issued);
}
len += sprintf(out_buf + len, "\n");
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index e260d19fa717f2..7f551d66f47f88 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -152,11 +152,6 @@ typedef u32 scsi_lun_t;
#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
-/* Retry 5 times every 2 second, then every minute */
-#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5
-#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200
-#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000
-
/* timeout value for "default timer" for fsf requests */
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
@@ -429,11 +424,7 @@ struct zfcp_scsi_dbf_record {
u32 fsf_seqno;
u64 fsf_issued;
union {
- struct {
- u64 fsf_reqid;
- u32 fsf_seqno;
- u64 fsf_issued;
- } new_fsf_req;
+ u64 old_fsf_reqid;
struct {
u8 rsp_validity;
u8 rsp_scsi_status;
@@ -915,8 +906,6 @@ struct zfcp_adapter {
wwn_t peer_wwnn; /* P2P peer WWNN */
wwn_t peer_wwpn; /* P2P peer WWPN */
u32 peer_d_id; /* P2P peer D_ID */
- wwn_t physical_wwpn; /* WWPN of physical port */
- u32 physical_s_id; /* local FC port ID */
struct ccw_device *ccw_device; /* S/390 ccw device */
u8 fc_service_class;
u32 hydra_version; /* Hydra version */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index da947e662031f6..e3c4bdd29a6080 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -2246,15 +2246,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
{
int retval;
- if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &erp_action->adapter->status)) &&
- (erp_action->adapter->adapter_features &
- FSF_FEATURE_HBAAPI_MANAGEMENT)) {
- zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
- atomic_set(&erp_action->adapter->erp_counter, 0);
- return ZFCP_ERP_FAILED;
- }
-
retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
if (retval == ZFCP_ERP_FAILED)
return ZFCP_ERP_FAILED;
@@ -2266,13 +2257,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
}
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
static int
zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
{
@@ -2350,48 +2334,40 @@ static int
zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
{
int ret;
- int retries;
- int sleep;
- struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_adapter *adapter;
+ adapter = erp_action->adapter;
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
- retries = 0;
- do {
- write_lock(&adapter->erp_lock);
- zfcp_erp_action_to_running(erp_action);
- write_unlock(&adapter->erp_lock);
- zfcp_erp_timeout_init(erp_action);
- ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
- if (ret == -EOPNOTSUPP) {
- debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
- return ZFCP_ERP_SUCCEEDED;
- } else if (ret) {
- debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
- return ZFCP_ERP_FAILED;
- }
- debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
+ write_lock(&adapter->erp_lock);
+ zfcp_erp_action_to_running(erp_action);
+ write_unlock(&adapter->erp_lock);
- down(&adapter->erp_ready_sem);
- if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
- ZFCP_LOG_INFO("error: exchange of port data "
- "for adapter %s timed out\n",
- zfcp_get_busid_by_adapter(adapter));
- break;
- }
- if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status))
- break;
+ zfcp_erp_timeout_init(erp_action);
+ ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
+ if (ret == -EOPNOTSUPP) {
+ debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
+ return ZFCP_ERP_SUCCEEDED;
+ } else if (ret) {
+ debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
+ return ZFCP_ERP_FAILED;
+ }
+ debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
- if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) {
- sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP;
- retries++;
- } else
- sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
- schedule_timeout(sleep);
- } while (1);
+ ret = ZFCP_ERP_SUCCEEDED;
+ down(&adapter->erp_ready_sem);
+ if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+ ZFCP_LOG_INFO("error: exchange port data timed out (adapter "
+ "%s)\n", zfcp_get_busid_by_adapter(adapter));
+ ret = ZFCP_ERP_FAILED;
+ }
+ if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) {
+ ZFCP_LOG_INFO("error: exchange port data failed (adapter "
+ "%s\n", zfcp_get_busid_by_adapter(adapter));
+ ret = ZFCP_ERP_FAILED;
+ }
- return ZFCP_ERP_SUCCEEDED;
+ return ret;
}
/*
@@ -3439,6 +3415,8 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
"(adapter %s, wwpn=0x%016Lx)\n",
zfcp_get_busid_by_port(port),
port->wwpn);
+ else
+ scsi_flush_work(adapter->scsi_host);
}
zfcp_port_put(port);
break;
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index c1ba7cf1b49619..700f5402a978fc 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -194,9 +194,10 @@ extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
- struct scsi_cmnd *);
+ struct scsi_cmnd *,
+ struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
- struct scsi_cmnd *,
+ struct scsi_cmnd *, struct zfcp_fsf_req *,
struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
struct scsi_cmnd *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 9f0cb3d820c06c..662ec571d73b5a 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -388,6 +388,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
case FSF_PROT_LINK_DOWN:
zfcp_fsf_link_down_info_eval(adapter,
&prot_status_qual->link_down_info);
+ zfcp_erp_adapter_reopen(adapter, 0);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -558,10 +559,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
- if (link_down == NULL) {
- zfcp_erp_adapter_reopen(adapter, 0);
- return;
- }
+ if (link_down == NULL)
+ goto out;
switch (link_down->error_code) {
case FSF_PSQ_LINK_NO_LIGHT:
@@ -643,16 +642,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
link_down->explanation_code,
link_down->vendor_specific_code);
- switch (link_down->error_code) {
- case FSF_PSQ_LINK_NO_LIGHT:
- case FSF_PSQ_LINK_WRAP_PLUG:
- case FSF_PSQ_LINK_NO_FCP:
- case FSF_PSQ_LINK_FIRMWARE_UPDATE:
- zfcp_erp_adapter_reopen(adapter, 0);
- break;
- default:
- zfcp_erp_adapter_failed(adapter);
- }
+ out:
+ zfcp_erp_adapter_failed(adapter);
}
/*
@@ -2304,6 +2295,35 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
return retval;
}
+/**
+ * zfcp_fsf_exchange_port_evaluate
+ * @fsf_req: fsf_req which belongs to xchg port data request
+ * @xchg_ok: specifies if xchg port data was incomplete or complete (0/1)
+ */
+static void
+zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
+{
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb *qtcb;
+ struct fsf_qtcb_bottom_port *bottom, *data;
+ struct Scsi_Host *shost;
+
+ adapter = fsf_req->adapter;
+ qtcb = fsf_req->qtcb;
+ bottom = &qtcb->bottom.port;
+ shost = adapter->scsi_host;
+
+ data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
+ if (data)
+ memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
+
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ fc_host_permanent_port_name(shost) = bottom->wwpn;
+ else
+ fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
+ fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+ fc_host_supported_speeds(shost) = bottom->supported_speed;
+}
/**
* zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request
@@ -2312,38 +2332,26 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
static void
zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
{
- struct zfcp_adapter *adapter = fsf_req->adapter;
- struct Scsi_Host *shost = adapter->scsi_host;
- struct fsf_qtcb *qtcb = fsf_req->qtcb;
- struct fsf_qtcb_bottom_port *bottom, *data;
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb *qtcb;
+
+ adapter = fsf_req->adapter;
+ qtcb = fsf_req->qtcb;
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
switch (qtcb->header.fsf_status) {
case FSF_GOOD:
+ zfcp_fsf_exchange_port_evaluate(fsf_req, 1);
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
-
- bottom = &qtcb->bottom.port;
- data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
- if (data)
- memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
- if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
- fc_host_permanent_port_name(shost) = bottom->wwpn;
- else
- fc_host_permanent_port_name(shost) =
- fc_host_port_name(shost);
- fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
- fc_host_supported_speeds(shost) = bottom->supported_speed;
break;
-
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
+ zfcp_fsf_exchange_port_evaluate(fsf_req, 0);
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
-
zfcp_fsf_link_down_info_eval(adapter,
&qtcb->header.fsf_status_qual.link_down_info);
break;
-
default:
debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
debug_event(adapter->erp_dbf, 0,
@@ -4203,11 +4211,11 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result);
if (scpnt->result != 0)
- zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt);
+ zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt, fsf_req);
else if (scpnt->retries > 0)
- zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt);
+ zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt, fsf_req);
else
- zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt);
+ zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt, fsf_req);
/* cleanup pointer (need this especially for abort) */
scpnt->host_scribble = NULL;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index e0803757c0fa05..9f6b4d7a46f334 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -242,7 +242,7 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
if ((scpnt->device != NULL) && (scpnt->device->host != NULL))
zfcp_scsi_dbf_event_result("fail", 4,
(struct zfcp_adapter*) scpnt->device->host->hostdata[0],
- scpnt);
+ scpnt, NULL);
/* return directly */
scpnt->scsi_done(scpnt);
}
@@ -446,7 +446,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
if (!old_fsf_req) {
write_unlock_irqrestore(&adapter->abort_lock, flags);
- zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL);
retval = SUCCESS;
goto out;
}
@@ -460,6 +460,8 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
adapter, unit, 0);
if (!new_fsf_req) {
ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
+ zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
+ old_fsf_req);
retval = FAILED;
goto out;
}
@@ -470,13 +472,16 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
/* status should be valid since signals were not permitted */
if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
- zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req,
+ NULL);
retval = SUCCESS;
} else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
- zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req,
+ NULL);
retval = SUCCESS;
} else {
- zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req);
+ zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req,
+ NULL);
retval = FAILED;
}
zfcp_fsf_req_free(new_fsf_req);
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index dfc07370f412ac..b29ac25e07f3a8 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -55,8 +55,6 @@ ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn);
ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn);
ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
-ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn);
-ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
@@ -241,8 +239,6 @@ static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_peer_wwnn.attr,
&dev_attr_peer_wwpn.attr,
&dev_attr_peer_d_id.attr,
- &dev_attr_physical_wwpn.attr,
- &dev_attr_physical_s_id.attr,
&dev_attr_card_version.attr,
&dev_attr_lic_version.attr,
&dev_attr_status.attr,